使用不同对象时模板特化的多重定义

2021-12-13 00:00:00 templates c++

当我在不同的目标文件中使用专用模板时,链接时出现多重定义"错误.我发现的唯一解决方案涉及使用内联"函数,但这似乎是一些解决方法.如何在不使用inline"关键字的情况下解决这个问题?如果那不可能,为什么?

When I use a specialized template in different object files, I get a "multiple definition" error when linking. The only solution I found involves using the "inline" function, but it just seems like some workaround. How do I solve that without using the "inline" keyword? If that's not possible, why?

示例代码如下:

paulo@aeris:~/teste/cpp/redef$ cat hello.h 
#ifndef TEMPLATE_H
#define TEMPLATE_H

#include <iostream>

template <class T>
class Hello
{
public:
    void print_hello(T var);
};

template <class T>
void Hello<T>::print_hello(T var)
{
    std::cout << "Hello generic function " << var << "
";
}

template <> //inline
void Hello<int>::print_hello(int var)
{
    std::cout << "Hello specialized function " << var << "
";
}

#endif

<小时>

paulo@aeris:~/teste/cpp/redef$ cat other.h 
#include <iostream>

void other_func();

<小时>

paulo@aeris:~/teste/cpp/redef$ cat other.c 
#include "other.h"

#include "hello.h"

void other_func()
{
    Hello<char> hc;
    Hello<int> hi;

    hc.print_hello('a');
    hi.print_hello(1);
}

<小时>

paulo@aeris:~/teste/cpp/redef$ cat main.c 
#include "hello.h"

#include "other.h"

int main()
{
    Hello<char> hc;
    Hello<int> hi;

    hc.print_hello('a');
    hi.print_hello(1);

    other_func();

    return 0;
}

<小时>

paulo@aeris:~/teste/cpp/redef$ cat Makefile
all:
    g++ -c other.c -o other.o -Wall -Wextra
    g++ main.c other.o -o main -Wall -Wextra

<小时>

最后:

paulo@aeris:~/teste/cpp/redef$ make
g++ -c other.c -o other.o -Wall -Wextra
g++ main.c other.o -o main -Wall -Wextra
other.o: In function `Hello<int>::print_hello(int)':
other.c:(.text+0x0): multiple definition of `Hello<int>::print_hello(int)'
/tmp/cc0dZS9l.o:main.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: ** [all] Erro 1

如果我取消注释 hello.h 中的内联",代码将编译并运行,但这对我来说似乎是某种解决方法":如果专用函数很大并且被多次使用怎么办?我会得到一个大的二进制文件吗?有没有其他方法可以做到这一点?如果是,如何?如果没有,为什么?

If I uncomment the "inline" inside hello.h, the code will compile and run, but that just seems like some kind of "workaround" to me: what if the specialized function is big and used many times? Will I get a big binary? Is there any other way to do this? If yes, how? If not, why?

我试图寻找答案,但我得到的只是使用内联",没有任何进一步的解释.

I tried to look for answers, but all I got was "use inline" without any further explanation.

谢谢

推荐答案

直观地说,当你完全特化某物时,它不再依赖于模板参数――所以除非你使特化内联,否则你需要把它在一个 .cpp 文件而不是一个 .h 中,否则你最终会违反大卫所说的一个定义规则.请注意,当您部分特化模板时,部分特化仍然依赖于一个或多个模板参数,因此它们仍然位于 .h 文件中.

Intuitively, when you fully specialize something, it doesn't depend on a template parameter any more -- so unless you make the specialization inline, you need to put it in a .cpp file instead of a .h or you end up violating the one definition rule as David says. Note that when you partially specialize templates, the partial specializations do still depend on one or more template parameters, so they still go in a .h file.

相关文章