Reputation: 25603
I try to specialize a template if a class has a special member function like this (found here in another example):
template <typename T>
class has_begin
{
typedef char one;
typedef long two;
template <typename C> static one test( decltype( &C::AnyFunc) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
enum { Yes = sizeof(has_begin<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
This works well until AnyFunc
is overloaded:
class B : public vector<int>
{
public:
void AnyFunc() const;
void AnyFunc();
};
How can I rewrite my test code to get a "Yes" from my template?
Upvotes: 5
Views: 177
Reputation: 157334
The use of an overloaded function name without arguments (13.4p1) must be resolved to a single overload (13.4p4), otherwise substitution failure will occur.
If you are testing for the existence of a member function then you should know the arguments you plan to call it with:
template <typename C> static one test(
typename std::add_pointer<decltype(std::declval<C>().AnyFunc())>::type);
In general, you can use a variadic template and a pattern similar to result_of
:
template <typename C, typename... Args> static one test(
typename std::add_pointer<decltype(
std::declval<C>(std::declval<Args>()...).AnyFunc())>::type);
Using add_pointer
allows this to work with function return types that are not allowable as function argument types (e.g. void
).
Upvotes: 2
Reputation: 24392
Found the version which works:
template <typename C> static one test( decltype(((C*)0)->AnyFunc())* ) ;
If you want to verify that object has const function, use this:
template <typename C> static one test( decltype(((const C*)0)->AnyFunc())* ) ;
this version will not detect function with arguments:
class B : public std::vector<int>
{
public:
//void AnyFunc() const;
//void AnyFunc();
int AnyFunc(int);
};
Upvotes: 1