您可以通过 ADL 从类型中测试是否namespace
可访问(由编译器查找)。
假设我们要检查类型是否A
来自namespace foo
,我们可以尝试使用只出现在foo
(例如泛型函数foo::foo_inner_func(T&&)
)中的类型,通过使用A
来查看我们是否到达命名空间。如果我们在 SFINAE 上下文中执行此操作,那么这可能会导致我们正在寻找答案:是否namespace foo
可以通过A
.
在许多情况下,这将是类型是否属于此命名空间的答案,但在某些情况下,它可能会将命名空间标识为可由 ADL 访问,即使该类型并非来自此命名空间。例如,if A
is fromnamespace foo
和B
which 派生自A
is from 另一个命名空间,仍然通过 ADL B
“看到” 。foo
也通过 ADL std::vector<A>
“看到” foo
(也通过 ADL“看到” std
)。
这里已经提出了使用 ADL 的想法:检查类型是否来自特定的命名空间。
这是允许查询任何类型(几乎)任何命名空间(几乎)的宏版本:
#define create_ns_checker(ns) \
namespace ns { \
template <typename T> \
constexpr std::true_type ns##FindmeNsADLHelper(T&&); \
} \
namespace ns##_type_traits { \
class ns##SecondBestMatchType {}; \
class ns##BestExactMatchType : public ns##SecondBestMatchType {}; \
namespace helpers { \
template <typename T> \
auto TestNs(ns##_type_traits::ns##BestExactMatchType) \
-> decltype(ns##FindmeNsADLHelper(std::declval<T>())); \
template <typename T> \
auto TestNs(ns##_type_traits::ns##SecondBestMatchType) \
-> std::false_type; \
} \
template <typename T> \
constexpr bool ns##IsFindmeNs() { \
return decltype(helpers::TestNs<std::decay_t<T>> \
(ns##BestExactMatchType{}))::value; \
} \
}
#define is_in_ns(Type, ns) \
(ns##_type_traits::ns##IsFindmeNs<Type>())
一个小型打印实用程序:
#define print_is_in_ns(Type, ns) \
[]() { \
std::cout << #Type << " in " << #ns << ": " \
<< is_in_ns(Type, ns) << std::endl; \
}()
使用宏创建检查器:
create_ns_checker(findme)
create_ns_checker(other)
create_ns_checker(std)
检查以下类型:
namespace other {
struct B {};
}
struct C {};
namespace findme {
struct A {};
namespace inner {
struct A {};
}
create_ns_checker(inner)
}
在 findme 上下文中进行测试:
namespace findme {
void test() {
using namespace other;
// add the below in and the results change, as it should!
// using inner::A;
using std::string;
std::cout << std::boolalpha;
print_is_in_ns(int, std); // false
print_is_in_ns(string, std); // true
print_is_in_ns(A, findme); // true
print_is_in_ns(A, inner); // false
print_is_in_ns(inner::A, findme); // false
print_is_in_ns(inner::A, inner); // true
print_is_in_ns(B, findme); // false
print_is_in_ns(B, other); // true
print_is_in_ns(C, findme); // false
}
}
主要测试:
int main() {
using std::string;
using findme::A;
std::cout << std::boolalpha;
print_is_in_ns(int, std); // false
print_is_in_ns(string, std); // true
print_is_in_ns(string, findme); // false
print_is_in_ns(findme::A, findme); // true
print_is_in_ns(findme::inner::A, findme); // false
print_is_in_ns(other::B, findme); // false
print_is_in_ns(other::B, other); // true
print_is_in_ns(C, findme); // false
print_is_in_ns(std::vector<A>, findme); // falsely says true :-(
print_is_in_ns(std::vector<A>, std); // true
std::cout << "-----------------" << std::endl;
findme::test();
}
代码:https ://godbolt.org/z/8Ed89v