As a follow-up to my previous question, I am trying to detect the existence of a template function that requires explicit specialization.
My current working code detects non-template functions (thanks to DyP's help), provided they take at least one parameter so that dependent name lookup can be used:
// switch to 0 to test the other case
#define ENABLE_FOO_BAR 1
namespace foo {
#if ENABLE_FOO_BAR
int bar(int);
#endif
}
namespace feature_test {
namespace detail {
using namespace foo;
template<typename T> decltype(bar(std::declval<T>())) test(int);
template<typename> void test(...);
}
static constexpr bool has_foo_bar = std::is_same<decltype(detail::test<int>(0)), int>::value;
static_assert(has_foo_bar == ENABLE_FOO_BAR, "something went wrong");
}
(the ENABLE_FOO_BAR
macro is just for testing purpose, in my real code I don't have such a macro available otherwise I wouldn't be using SFINAE)
This also works perfectly with template functions when their template arguments can automatically be deduced by the compiler:
namespace foo {
#if ENABLE_FOO_BAR
template<typename T> int bar(T);
#endif
}
However when I try to detect a template function that requires explicit specialization, the static_assert
kicks in when foo::bar()
exists:
namespace foo {
#if ENABLE_FOO_BAR
template<typename T, typename U> T bar(U);
#endif
}
//...
// error: static assertion failed: something went wrong
Obviously the compiler can't deduce the template arguments of bar()
so the detection fails. I tried to fix it by explicitly specializing the call:
template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
// explicit specialization ^^^^^^^^
This works fine when foo::bar()
exists (the function is correctly detected) but now all hell breaks loose when foo::bar()
doesn't exist:
error: ‘bar’ was not declared in this scope
template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
^
error: expected primary-expression before ‘int’
template<typename T> decltype(bar<int, T>(std::declval<T>())) test(int);
^
// lots of meaningless errors that derive from the first two
It seems my attempt at explicit specialization failed because the compiler doesn't know that bar
is a template.
I'll spare you everything I tried to fix this and get straight to the point: how can I detect the existence of a function such as template<typename T, typename U> T bar(U);
that requires explicit specialization in order to be instantiated?