c++ - 模板运算符重载函数上的 undefined symbol

标签 c++ templates namespaces operator-overloading

我有这个函数声明:

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

和这个函数定义:

namespace a {
    ...
    class A {
        ...
        template<class T> A& operator<<(T);

我称它为:

a::A b;
b << 1;

这是生成文件:

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

它给了我:

Undefined symbols: a::A& a::A::operator<< <int>(int)

这是为什么?

最佳答案

一旦 T 表示的类型(在您的情况下为 int)实际已知,函数模板将在编译时转换为实际函数。但是,在编译main.cpp 之前,情况并非如此。 A.cpp编译时,模板函数并没有实例化为实际函数,因此生成的目标文件不包含函数的二进制版本。

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

  1. 在头文件中包含函数定义。即,使

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

    头文件的一部分,并从.cpp文件中移除函数定义。

    这样做的效果是包含此 header 的任何 .cpp 文件将能够使用模板的任何实例化,即对于 T 的任何值。

  2. 或者,在A.cpp 中包含显式模板实例化语句:

    template a::A& a::A::operator<<(int out);
    

    这将导致编译器在编译A.cpp 时实际实例化模板,并将编译后的函数包含在目标文件中。因此,链接器可以在将 main.oA.o 链接在一起时找到它,一切都很好。缺点是它仅适用于您为其提供显式实例化的特定类型(在本例中,仅 int)。

关于c++ - 模板运算符重载函数上的 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13150412/

相关文章:

c++ - 赋值运算符和相等运算符中的宽字符和字符

c++ - 如何为类编写 "get"方法模板

scala - A1 类型的神秘成员 "default"=> B1

c++ - 如何在 Linux 中打开包含非 Ascii 字符串的 wchar_t* 文件?

c++ - 需要类型名错误(模板相关错误)

c++ - 对物体施加重力

c++ - 未找到使用表达式模板化的静态 constexpr 成员函数

c++ - 在 C++ 中向下转换模板类型名称对象

Javascript:当它包含一个点时获取构造函数名称

php - PHP 中的命名空间是什么?