Pre C++17 you can's compile/not compile different parts of the same function with if constexpr
.
So, pre C++17, you have to do, somewhere, two different functions.
An example: if you prepare a couple of helper functions
template <typename T>
auto call_foo_h (T t, int) -> decltype( t.foo() )
{ return t.foo(); }
template <typename T>
auto call_foo_h (T t, long) -> decltype( foo(t) )
{ return foo(t); }
that are SFINAE enabled only if T::foo()
exist (the first one) or if a free foo()
exist (the second one), you can write call_foo()
as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0); }
//......................^ a int value
Observe the second (unused) parameter in call_foo_h()
; an int
in the T::foo()
version, a long
in the free version.
Here is the trick: calling call_foo_h
with an int
(0
) you call preferably the int
version (the T::foo()
), when available, and the long
version otherwise.
How about the reverse case: preferring a free function foo
before the member function?
In this case write call_foo()
as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0L); }
//......................^^ a long value
That is: call call_foo_h
with a long
value, giving the precedence to the free foo()
version.