I’ve got (probably) a simple question.
When do I have to declare a function used in a template?
The following code prints out (using gcc >=4.1):
init my A object
no init
Using gcc 4.0 the following code prints out:
init my A object
init my string object
#include <iostream>
#include <string>
template<typename T>
void init(T& t){
std::cout << "no init" << std::endl;
}
// void init(std::string& t);
template <typename T>
void doSomething(T& t){
init(t);
// do some further stuff
}
void init(std::string& t){
std::cout << "init my string object" << std::endl;
}
class A{
};
void init(A& t){
std::cout << "init my A object" << std::endl;
}
int main(){
A a;
doSomething(a);
std::string s("test");
doSomething(s);
return 0;
}
What is the difference between the usage of std::string and A?
Shouldn’t there be the same behaviour?
With the additional forward declaration it works fine,
but when do I need it?
Cheers,
CSpille
Functions at the instantiation point are looked up only using argument dependent lookup (looking up functions in the namespaces associated with a function argument). Normal lookup is only done at the point of the template definition.
So for
std::string, only the genericinitfunction template is visible and called, since there is no specific one for it in namespacestd. ForA, the more specific function is found in the global namespace ofA.If you forward declare the string specific function to appear prior to
doSomething, normal unqualified lookup finds it at the definition and uses it later on.If you call
initas follows, it inhibits argument dependent lookup, and will thus use the generic template forAtoo.(As a side-node: In that case, not only argument dependent lookup is inhibited at instantiation, but
initwon’t be a dependent name in the first place – only non-parenthesized and unqualified function names are made dependent. Thus only non-ADL lookup at definition is done anyway and no lookup at instantiation is taken place what-so-ever, even if there would be a form different from ADL that would be done there.)