我正在解决一个经典问题:检查某些名称空间中是否存在自由函数。讨论了例如here。模板元编程:检查后面定义的函数的存在
但是,有一个轻微的扭曲:函数的定义可能会出现后面比检查器类。这是一个例子。
struct Yes {};
struct No {};
struct YesButLater {};
void f(Yes) {}
template<typename T, typename Enable = void>
struct HasF : public std::false_type {};
template<typename T>
struct HasF<T, decltype(void(::f(T())))> : public std::true_type {};
void f(YesButLater) {}
int main() {
cout << HasF<Yes>::value << endl; // 1
cout << HasF<No>::value << endl; // 0
cout << HasF<YesButLater>::value << endl; // 0, expected 1
}
f(YesButLater)
晚于HasF
助手类中声明,而且,虽然我实例化模板f(YesButLater)
定义后,助手不会注意到它。
所以,这里是问题1:我该如何处理它?
现在又多了一个更好奇的例子。
template<typename T>
struct HasF<T, decltype(void(f(T())))> : public std::true_type {};
void f(YesButLater) {}
void f(std::string) {}
int main() {
cout << HasF<YesButLater>::value << endl; // 1 (but what's the difference?)
cout << HasF<std::string>::value << endl; // 0, expected 1
}
注意,我从decltype(...)
表达除去::
。现在由于某种原因f(YesButLater)
被注意到由HasF
,但f(std::string)
仍然不明确。
问题2:为什么我们在本例中观察到::f(T())
和f(T())
的不同行为?此外,YesButLater
和std::string
之间的区别是什么?
我认为有一些与命名空间查找技巧,但我无法得到的东西。
我的猜测 - 这是由于[adl](http://en.cppreference.com/w/cpp/language/adl)规则... –
@ W.F。是的,可能,尽管我仍然不明白为什么::重要,因为我在示例中始终使用全局名称空间。 –