In C++11, to find out whether a class has a member function size
, you could define the following test helper:
template <typename T>
struct has_size_fn
{
typedef char (& yes)[1];
typedef char (& no)[2];
template <typename C> static yes check(decltype(&C::size));
template <typename> static no check(...);
static bool const value = sizeof(check<T>(0)) == sizeof(yes);
};
Is there a similar trick for doing this in C++98 without relying on compiler extensions such as typeof
?
Actually, your detection is potentially erroneous.
The problem is that all you are detecting is that C
has a member size
:
If you wish to harden the detection, you should attempt to detect only the right size
(for whatever right is). Here is such a hardened detection.
template <typename T>
class has_size {
private:
typedef char Yes;
typedef Yes No[2];
template <typename U, U> struct really_has;
template <typename C> static Yes& Test(really_has <size_t (C::*)() const,
&C::size>*);
// EDIT: and you can detect one of several overloads... by overloading :)
template <typename C> static Yes& Test(really_has <size_t (C::*)(),
&C::size>*);
template <typename> static No& Test(...);
public:
static bool const value = sizeof(Test<T>(0)) == sizeof(Yes);
};
Edit: with overloads.
The trick to deal with incorrect size
members is the really_has
structure. I make no pretense that it is perfect, though...
In C++11, things are simpler (though no less verbose) because you can detect things by use directly. The equivalent trait is thus:
template <typename T>
class has_size {
private:
typedef char Yes;
typedef Yes No[2];
template<typename C> static auto Test(void*)
-> decltype(size_t{std::declval<C const>().size()}, Yes{});
template<typename> static No& Test(...);
public:
static bool const value = sizeof(Test<T>(0)) == sizeof(Yes);
};
However, the recommended method in C++ is not to use traits if you can; in functions for example you can use decltype
right in the type signature.