Edit: The short answer to my question is that I had a mistaken view of what SFINAE can do and it does not check the function body at all: does sfinae instan
I don't have the time to check this now, but you can add an specialization of Final
: template
(which also helps ensure that the type is always a Inner
. With that you can extract the type used to instantiate Inter
.
Now the second problem is how to use SFINAE to detect whether a member function exists. I believe this should not be too complex (if you don't need to make this generic):
// Find out whether U has `void f()` member
template
struct has_member_f {
typedef char yes;
struct no { char _[2]; };
template
static yes impl( T* );
static no impl(...);
enum { value = sizeof( impl( static_cast(0) ) ) == sizeof(yes) };
};
You might be able to extend this a bit to make it a bit more generic, but the name of the function I don't think you can make generic. Of course, you could write that as a macro that generates has_member_##arg
and uses &T:: arg
. The type of the member is probably easier to generalize...
Alternatively, since I don't think this can be made generic, you can use the trick inside has_member
directly in your type: provide two callFuncA
overloads, one templated with the optional second argument with the signature that you want and defaulted to &T::FuncA
that forwards the call, the other with ellipsis that is a noop. Then callFuncs
would call callFuncA
and callFuncB
, and SFINAE will dispatch to either the forwarder or the noon and you get your desired behavior.
template
struct Final< Inter >
{
template
void callFuncA( Inter* x ) {
x.FuncA();
}
void callFuncA(...) {}
void CallFuncs() {
callFuncA(&t); // Cannot pass nonPOD types through ...
// Similarly TryCallFuncB(t);
}
Inter t;
};