On Tue, Oct 30, 2012 at 10:16 AM, Roy Stogner <royst...@ices.utexas.edu> wrote:
>
> Anyone know of an existing traits class where the equivalent of
> that_traits_class<T>::is_container specializes to true for container
> types (i.e. any types returning iterators from begin() and end()) T?
> It would be easy to create one but I'd rather not reinvent the wheel.


Hmm.... this might be useful for you.  It implements a print function
which works for containers and non-containers, but I think the idea is
general enough.



Here's super_print.h:


#include <iostream>
#include <iterator> // ostream_iterator

// A class for determining whether T is a container,
// which in this case means that it has a member of
// type 'iterator'
template <typename T>
class is_container
{
  // true_type and false_type must have different sizes so
  // that they compare inequal by sizeof.  Thus, we use the
  // same base type of char, but use an array of such for
  // the false_type.
  typedef char true_type;
  struct false_type { true_type array[2]; };

  // If the compiler can make sense of U::iterator, this
  // function will be instantiated...
  template <typename U>
  static true_type has_iterator_checker(typename U::iterator *);

  // ... otherwise this function returning false_type will
  // be instantiated.
  template <typename U>
  static false_type has_iterator_checker(...);


public:
  // The interface for this class.  'value' will be a
  // boolean expression equivalent to true if type T
  // is a container, and false otherwise.  The argument
  // of zero which is passed in should be thought of as
  // (T::iterator*) NULL.  Since this is an enum, its
  // value is determined at compile-time.
  enum { value = (sizeof(has_iterator_checker<T>(0)) ==
                  sizeof(true_type)) };
};



template <bool Cond, class T = void>
struct enable_if
{
  typedef T type;
};

// Specialization of the enable_if class
// for Cond==false is an empty class, that is,
// 'type' is not defined.
template <class T>
struct enable_if<false, T>
{};



// Version of the print function for types T
// which *are not* containers.  In this case, we
// just print the value directly using std::cout.
//
// If T is not a container, the compiler will see
// a function prototype like:
//
// void super_print(T const& t);
//
// otherwise, it sees something like:
//
// <blank> super_print(T const& t);
//
// but this isn't an error because SFINAE.
template <typename T>
typename enable_if<!is_container<T>::value>::type
super_print(T const &t)
{
  std::cout << t << std::endl;
}


// Version of the print function for types T which
// *are* containers.  In this case, we use the
// std::copy algorithm to print all the entries.
//
// As in the previous case, if T is not a container,
// this function expands to something that doesn't make
// sense to the compiler, but it isn't an error because
// SFINAE.
template <typename T>
typename enable_if<is_container<T>::value>::type
super_print(T const &t)
{
  typedef typename T::value_type value_type;
  std::copy(t.begin(),
            t.end(),
            std::ostream_iterator<value_type>(std::cout, " "));
  std::cout << std::endl;
}



And here's a sample main.

//#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <list>

// SFINAE = Substitution Failure Is Not An Error
#include "super_print.h"




int main()
{
  super_print(10);
  std::vector<int> b;
  b.push_back(1);
  b.push_back(2);
  b.push_back(3);
  super_print(b);

  std::map<int,int> m;
  m.insert( std::make_pair(1,1) );

  // Error, map::value_type is pair<key,value>, which has no default
  // operator<< defined
  // super_print(m);

  std::list<int> l;
  l.push_back(5);
  l.push_front(4);
  l.push_back(6);
  super_print(l);
}



-- 
John

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
Libmesh-devel mailing list
Libmesh-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libmesh-devel

Reply via email to