开发者

When do I have to declare a function used in a template?

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>
开发者_Python百科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 generic init function template is visible and called, since there is no specific one for it in namespace std. For A, the more specific function is found in the global namespace of A.

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 init as follows, it inhibits argument dependent lookup, and will thus use the generic template for A too.

template <typename T>
void doSomething(T& t){
    (init)(t);
    // won't do ADL
}

(As a side-node: In that case, not only argument dependent lookup is inhibited at instantiation, but init won'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.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜