我想使用 SFINAE 检查特定命名空间中是否存在函数。我发现SFINAE 可以测试来自另一个命名空间的自由函数,它可以完成这项工作,但有些事情我不明白。
目前我有这个工作代码,直接来自链接的问题:
// 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");
(该ENABLE_FOO_BAR
宏仅用于测试目的,在我的真实代码中我没有这样的宏,否则我不会使用 SFINAE)
但是,一旦我放入detail_overload::bar()
任何其他命名空间(using
根据需要调整指令),检测就会静默中断,并且static_assert
在存在时foo::bar()
启动。它仅在“虚拟”bar()
重载直接位于全局命名空间或命名空间的一部分::detail_overload
(注意全局::
范围)时才有效。
// 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;
//...
我意识到这与我链接的问题完全相同,并且如前所述,我已经有了一个可行的解决方案,但是没有解决的问题是为什么会发生这种情况?
作为一个附带问题,有没有办法在不污染全局命名空间的情况下实现正确的 SFINAEbar()
检测detail_overload
?正如您可以从非工作示例中猜到的那样,我想将所有内容整齐地包装在一个feature_test
命名空间中。