我正在解決一個經典問題:檢查某些名稱空間中是否存在自由函數。討論了例如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。是的,可能,儘管我仍然不明白爲什麼::重要,因爲我在示例中始終使用全局名稱空間。 –