I'm solving a classical problem: check if there exists a free function in some namespace. It is discussed, e.g., here.
However, there is a slight twist: the definition of the function may appear later than the checker class. Here is an example.
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)
is declared later than HasF
helper class, and, although I instantiate the template after f(YesButLater)
was defined, the helper doesn't notice it.
So, here is question 1: how can I deal with it?
Now one more, more curious, example.
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
}
Note that I removed ::
from the decltype(...)
expression. Now for some reason f(YesButLater)
is noticed by HasF
, but f(std::string)
still remains obscure.
Question 2: Why do we observe different behaviour for ::f(T())
and f(T())
in this example? Moreover, what is the difference between YesButLater
and std::string
?
I think that there is some trick with namespace lookup but I cannot get the thing.