I want to check for the existence of a function in a specific namespace using SFINAE. I have found SFINAE to test a free function from another namespace which does the job, but there are some things I don't understand.
Currently I have this working code, straight from the linked question:
// switch to 0 to test the other case
#define ENABLE_FOO_BAR 1
namespace foo {
#if ENABLE_FOO_BAR
int bar();
#endif
}
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
namespace detail {
using namespace detail_overload;
using namespace foo;
template<typename T> decltype(bar()) test(T);
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)
However, as soon as I put detail_overload::bar()
in any other namespace (adjusting the using
directive as needed), the detection breaks silently and the static_assert
kicks in when foo::bar()
exists. It only works when the "dummy" bar()
overload is directly in the global namespace, or part of the ::detail_overload
namespace (note the global ::
scope).
// breaks
namespace feature_test {
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
namespace detail {
using namespace detail_overload;
using namespace foo;
//...
// breaks
namespace feature_test {
template<typename... Args> void bar(Args&&...);
namespace detail {
using namespace foo;
//...
// breaks
namespace detail {
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
using namespace detail_overload;
using namespace foo;
//...
// works
template<typename... Args> void bar(Args&&...);
namespace feature_test {
namespace detail {
using namespace foo;
//...
// works
namespace detail_overload {
template<typename... Args> void bar(Args&&...);
}
namespace feature_test {
namespace detail {
using namespace detail_overload;
using namespace foo;
//...
I realize this is the very same problem as the question I linked to, and as mentioned I already have a working solution, but what is not addressed there is why precisely does this happen?
As a side question, is there any way to achieve correct SFINAE detection without polluting the global namespace with either bar()
or a detail_overload
namespace? As you can guess from the non-working examples, I'd like to neatly wrap everything in a single feature_test
namespace.