On Tue, Oct 30, 2012 at 10:16 AM, Roy Stogner <[email protected]> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-devel