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