First, you'll want to make the decision at compile time, since
otherwise, you'll need to provide the function, even if you
never go into the branch. I can imagine something like:
template <typename T, void (T::*)() > struct HasBar;
template <typename T>
void doBar( HasBar<&T::bar>* ) { T::bar(); }
template <typename T>
void doBar( ... ) {}
template <typename T>
class X
{
static void f()
{
doBar<T>( 0 );
}
};
It's a more or less classic trick; if &T::bar
fails (because
T doesn't have a member bar), then the instantiation of doBar(
HasBar<...>)
fails, the function is not added to the overload
set, so the other one is called. If &T::bar
is a legal
expression, both function templates can be successfully
instantiated, and the conversion of 0
to a pointer is chosen
before a match with ...
(which is always the last resort when
determining function overload resolution).
EDIT:
I missed the fact that the function was static. The above is
for a non-static function. For a static function, change the
first line to:
template <typename T, void (*)() struct HasBar;
The rest should work as is.