Consider the following class:
class MyClass
{
public:
template<class T> typename T::result_type apply(T& func)
{
if (is_int())
{
return func(int(0));
}
return func(double(0));
}
...
};
(The code does not look terribly useful, but it is only a contrived sample to demonstrate my point)
Anyway, a typical functor would be something like this:
struct MyFunc
{
typedef void result_type;
template<class V> void operator()(V)
{
// do something
}
};
And one would use it like so:
MyClass c;
MyFunc f;
c.apply(f);
My question is this – can MyClass::apply be changed to recognize a slightly different version of the functor in addition to the original one, for instance the one expecting the caller object reference to be passed along with all the other parameters, something like this:
struct MyFuncEx
{
typedef void result_type;
template<class V> void operator()(const MyClass& caller, V)
{
// do something
}
};
So, the following code would compile too:
MyClass c;
MyFunc f;
c.apply(f);
MyFuncEx f2;
c.apply(f2);
As a bonus I would like the compilation to fail if the functor contains both overloads, i.e. the following should fail the compilation:
struct MyFuncSmartAss
{
typedef void result_type;
template<class V> void operator()(V)
{
// do something
}
template<class V> void operator()(const MyClass& caller, V)
{
// do something
}
};
...
MyClass c;
c.apply(MyFuncSmartAss());
But, it is not that important as long as the longer overload takes the precedence over the shorter one.
It really depends whether you have C++11 or not. This should solve the overload issue in C++11 (*):
How does it work ?
decltypecreates an unevaluated context. The compiler performs regular overload resolution of the expression but only cares about the type. If an error occurs (theoperator()does not exist inf), then we hit SFINAE and this overload ofapplyis discardedFprovides both operators) then the call is ambiguous(*) I am not too sure about the correctness of the trailing-return-type specification, and more specifically the use of
thisand_arg. Both Clang 3.0 and gcc 4.5.2 error out. This can be worked around, just get a bit more verbose.In action at ideone with this workaround:
EDIT: to cope with the
int/doublerequirement.