gpt4 book ai didi

c++ - 模板特化歧义 : either specialized or original method may be linked

转载 作者:行者123 更新时间:2023-11-30 03:30:27 26 4
gpt4 key购买 nike

查看 tps.hpp 中的 base::m_visible 方法(它是“默认”):

#include <sstream>
#include <iostream>

template <typename T> struct base
{
void m_log() const;
void m_visible() const;
};

struct inheritor: base<inheritor>
{
void log() const;
};

template <typename T> void base<T>::m_log() const
{
std::ostringstream os;
m_visible();
os.str(""); // We have «default/default» if comment here, :-0
std::cout << os.str();
}

template <typename T> void base<T>::m_visible() const
{
std::cout
<< "default" << std::endl
;
}

专门用于 tps_spec.cpp 中的 inheritor 结构(名为 «spec»):

#include "tps.hpp"

template <> void base<inheritor>::m_visible() const
{
std::cout
<< "spec" << std::endl
;
}

void inheritor::log() const
{
m_log();
}

并从 tps_main.cpp 进一步调用:

#include "tps.hpp"

int main(int, char **argv)
{
std::cout << argv[0] << ": ";
inheritor().m_log(); // We have «spec/spec» if call inheritor::log
return 0;
}

结果取决于编译单元的顺序 (GCC 4.8.4):

g++ -Wall -O3 -o tps1 tps_spec.cpp tps_main.cpp && g++ -Wall -O3 -o tps2 tps_main.cpp tps_spec.cpp && ./tps1 ; ./tps2
./tps1: spec
./tps2: default

这只会在优化 -O3 时发生。任何带有注释标记的实验版本都会产生不同的结果。 为什么?

最佳答案

因为这是未定义的行为。

如果一个模板是特化的,那么这种特化必须在任何地方都“可见”。

您在一个翻译单元中声明并实现特化。那个专门化的模板声明,基本上,完全在那个翻译单元内部,并且专门化只对那个翻译单元可见。您的 tps_main 翻译单元对模板特化没有可见性,也没有任何知识;因此,将其与具有此模板特化可见的不同翻译单元链接在一起会导致未定义的行为。

您需要在头文件中声明并定义(除了一些在这里不是很相关的异常(exception))特化,以便包含头文件的每个翻译单元具有模板定义的文件也将具有特化的定义。

模板特化不是模板的某种“实现”,用于专门的模板实例。模板特化基本上是一个完全独立的类声明。因此,如果您有一个使用该类的翻译单元,则它必须声明该类。

您不能只在一个翻译单元中声明一个类,然后期望在另一个翻译单元中使用它而不让其他翻译单元看到该声明。

基本上,您链接在一起的所有翻译单元必须具有相同的类、对象和模板声明。这包括模板特化。

这只是 C++ templates can only be portably defined in header files 的一种迂回说法.

关于c++ - 模板特化歧义 : either specialized or original method may be linked,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44960450/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com