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

时间:2023-03-09
本文介绍了模板运算符重载函数上的未定义符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我有这个函数声明:

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

它给了我:

未定义符号:a::A&a::A::operator<<(int)

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

这是为什么?

推荐答案

函数模板会在编译时变成一个实际的函数,一旦T所代表的类型(即int 在你的情况下)实际上是已知的.但是,在编译 main.cpp 之前,情况并非如此.编译A.cpp时,模板函数并未实例化为实际函数,因此生成的目标文件不包含该函数的二进制版本.

The function template will be turned into an actual function at compile time, once the type represented by T (that is, int in your case) is actually known. However, this is not the case before main.cpp is compiled. At the time when A.cpp is compiled, the template function is not instantiated into an actual function, therefore the object file generated doesn't include the binary version of the function.

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

There are two ways to solve this.

  1. 在头文件中包含函数定义.也就是说,使

  1. Include the function definition in your header file. That is, make

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

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

a part of the header file, and remove the function definition from the .cpp file.

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

The effect of this is that any .cpp file that includes this header will be able to use any instantiation of the template, i.e. for any value of T.

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

Alternatively, include an explicit template instantiation statement in A.cpp:

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

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

This will cause the compiler to actually instantiate the template when A.cpp is compiled, and to include the compiled function in the object file. Hence the linker can find it when linking main.o and A.o together, and all is fine. The disadvantage is that it will only work for the specific types (in this case, only int) that you provided explicit instantiations for.

这篇关于模板运算符重载函数上的未定义符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:什么是“常规类型"?在移动语义的上下文中? 下一篇:C++ 标准实践:虚拟接口类与模板

相关文章