2

我有(可能)一个简单的问题。什么时候必须声明模板中使用的函数?打印出以下代码(使用 gcc >=4.1):

初始化我的 A 对象

没有初始化

使用 gcc 4.0 打印出以下代码:

初始化我的 A 对象

初始化我的字符串对象

#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;
}

std::string 和 A 的用法有什么区别?不应该有相同的行为吗?

使用附加的前向声明它可以正常工作,但是我什么时候需要它?

干杯,CSpille

4

1 回答 1

4

仅使用参数相关查找(在与函数参数关联的命名空间中查找函数)查找实例化点处的函数。正常查找仅在模板定义处进行。

所以对于std::string,只有通用init函数模板是可见和调用的,因为在 namespace 中没有特定的模板std。对于A,更具体的功能可以在 的全局命名空间中找到A

如果您前向声明字符串特定函数出现在 之前doSomething,则正常的非限定查找会在定义中找到它并稍后使用它。

如果您init按如下方式调用,它会禁止依赖于参数的查找,因此也将使用通用模板A

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

(作为一个侧节点:在这种情况下,不仅参数依赖查找在实例化时被禁止,而且init首先不会是依赖名称 - 只有非括号和不合格的函数名称是依赖的。因此只有非无论如何都会在定义时进行 ADL 查找,并且在实例化时不会进行任何查找,即使会在那里完成与 ADL 不同的形式。)

于 2010-07-05T09:41:45.753 回答