代码之家  ›  专栏  ›  技术社区  ›  Spille

何时必须声明模板中使用的函数?

  •  2
  • Spille  · 技术社区  · 16 年前

    我(可能)有一个简单的问题。 打印出以下代码(使用gcc>=4.1):

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

    初始化我的字符串对象

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

    难道不应该有同样的行为吗?

    加上额外的远期申报,一切正常,

    干杯, 斯皮尔

    1 回复  |  直到 6 年前
        1
  •  4
  •   Johannes Schaub - litb    16 年前

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

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

    如果转发,则声明要在之前显示的特定于字符串的函数 doSomething

    如果你打电话 初始化 如下所示,它禁止参数相关的查找,因此将使用泛型模板 A 我也是。

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

    初始化 首先不会是从属名称-只有非圆括号和非限定的函数名才成为从属名称。因此,不管怎样,只在定义时进行非ADL查找,在实例化时也不会进行任何查找,即使有一种与ADL不同的形式在那里进行)