C++ 模板运算符重载函数上的未定义符号

C++ 模板运算符重载函数上的未定义符号,c++,templates,namespaces,operator-overloading,C++,Templates,Namespaces,Operator Overloading,我有这个功能声明: template<class T> a::A& a::A::operator<<(T out) { std::cout << out; return (*this); } 它给了我: 未定义的符号:a::a&a::a::operator一旦T表示的类型(即在您的例子中,int表示的类型)实际已知,函数模板将在编译时转换为实际函数。但是,在编译main.cpp之前,情况并非如此。编译A.cpp时,模板函数未实例化为实

我有这个功能声明:

template<class T>
a::A& a::A::operator<<(T out) {
    std::cout << out;
    return (*this);
}
它给了我:


未定义的符号:a::a&a::a::operator一旦
T
表示的类型(即在您的例子中,
int
表示的类型)实际已知,函数模板将在编译时转换为实际函数。但是,在编译
main.cpp
之前,情况并非如此。编译
A.cpp
时,模板函数未实例化为实际函数,因此生成的目标文件不包括函数的二进制版本

有两种方法可以解决这个问题

  • 在头文件中包含函数定义。也就是说,制造

    template<class T>
    a::A& a::A::operator<<(T out) {
        std::cout << out;
        return (*this);
    }
    
    这将导致编译器在编译
    A.cpp
    时实际实例化模板,并将编译后的函数包含在目标文件中。因此,链接器可以在将
    main.o
    A.o
    链接在一起时找到它,一切正常。缺点是它只适用于您为其提供显式实例化的特定类型(在本例中,仅适用于
    int


  • 尝试将定义更改为:

    template<class T>
    a::A& a::A::operator<< <T> (T out) {
        std::cout << out;
        return (*this);
    }
    
    模板
    
    a::a&a::a::运算符是与函数定义在同一文件中的调用吗?或者它们是分开的,例如在.h和.cpp之间?@jogojapan,它们是分开的。每个代码的每个部分都在一个单独的文件中。第一个进入
    A.cpp
    ,第二个进入
    A.hpp
    ,第三个进入
    main.cpp
    。这就是问题所在。您必须在.hpp文件中包含定义(顺便说一句,您在问题文本中混淆了声明和定义),或者在.cpp文件中为
    int
    添加一个显式实例化。请参见此处:这是不正确的语法。主模板定义不允许像这样在尖括号中指定类型。(如果这是一个模板专门化,尖括号中的类型就不是模板参数。)@jogojapan好吧,好吧,我错了。我通常使用模板类,而不是函数或成员。对不起,这对我有用。。。声明和定义现在都在.hpp中,对吗?在.cpp文件中没有与此函数相关的内容,对吗?您是否删除了旧的.o文件并重新编译了所有内容?
    app: main.o A.o
        g++ main.o A.o -o app
    
    main.o: main.cpp
        g++ -c main.cpp
    
    A.o: A.cpp
        g++ -c A.cpp
    
    template<class T>
    a::A& a::A::operator<<(T out) {
        std::cout << out;
        return (*this);
    }
    
    template a::A& a::A::operator<<(int out);
    
    template<class T>
    a::A& a::A::operator<< <T> (T out) {
        std::cout << out;
        return (*this);
    }