I have a piece of code that compiles using icc or visual c++ but does not when I use gcc or clang.
The problem comes from the fact that gcc/clang want bindTo(std::string& s, const int& i) to be defined before A<T>::bind(T& t) or callBindTo(T& t) definition and not just before code instantiation.
My question is: Why Visual and icc does not require it ? and which compiler have the right behavior with respect to the standard ?
#include <string>
template <typename T>
class A
{
public:
static void bind(T& t);
};
template <typename T>
void A<T>::bind(T& t)
{
std::string s;
bindTo(s, t);
}
template <typename T>
void callBindTo(T& t)
{
std::string s;
bindTo(s, t);
}
void bindTo(std::string& s, const int& i)
{
s = i;
}
int main()
{
int i;
A<int>::bind(i);
callBindTo(i);
}
GCC and Clang have the correct implementation. As the comments hint, the name t is looked up during instantiation, in the second name lookup phase, when T==int. This doesn't introduce any additional namespaces for Argument-Dependent Lookup. The compiler therefore has to look for all declarations of bind, in the global namespace, up to the point where it's actually used.
The last part is important. The scope for lookups is determined by the location of the template definition, not by the location of the first instantiation. This is a good thing. What if there were 5 instantiations, with 5 increasingly big overload sets? You'd have to instantiate the template each time, redoing overload resolution, and potentially getting 5 different results.
If you don't think that's bad enough, how would you deal with this in name mangling? You'd have callBindTo<int> and callBindTo<int>, two instantiations that could only be distinguished by the overload set of bind at their point of instantiation.
No, the current rules are sane. Yes, the Argument Dependent Lookup can add extra namespaces, and that's tricky, but all instantiations of callBindTo<std::string> add the same namespace std. And with that example, we see it's a good thing you called your function bindTo and not bind - you almost dragged in std::bind.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With