The following code of mine should detect whether T
has begin
and end
methods:
template
struct is_contai
Why are you going to all that effort? If you want to check if U::begin()
exists, why not try it?
template
struct is_container
{
template static char test(U* u,
typename U::const_iterator b = ((U*)0)->begin(),
typename U::const_iterator e = ((U*)0)->end());
template static long test(...);
enum { value = (1 == sizeof test(0)) };
};
In addition to checking for the existance of U::begin()
and U::end()
, this also checks whether they return something that is convertible to a const_iterator
. It also avoids the pitfall highlighted by Stephan T. Lavavej by using a call expression that must be supported, instead of assuming a particular signature.
[edit] Sorry, this relied on VC10's template instantiation. Better approach (puts the existance check in the argument types, which do participate in overloading):
template struct is_container
{
// Is.
template
static char test(U* u,
int (*b)[sizeof(typename U::const_iterator()==((U*)0)->begin())] = 0,
int (*e)[sizeof(typename U::const_iterator()==((U*)0)->end())] = 0);
// Is not.
template static long test(...);
enum { value = (1 == sizeof test(0)) };
};