c++ - 模板 C++ 链接程序对ODR冲突保持沉默的原因?

  显示原文与译文双语对照的内容
90 5

让我们来考虑一些综合但有表现力的例子。假设我们有 Header.h:

Header1.h

#include <iostream>
//Define generic version
template<typename T>
inline void Foo()
{
 std::cout <<"Genericn";
}

Header2.h

void Function1();

Header3.h

void Function2();

Source1.cpp

#include"Header1.h"
#include"Header3.h"
//Define specialization 1
template<>
inline void Foo<int>()
{
 std::cout <<"Specialization 1n";
}
void Function1()
{
 Foo<int>();
}

稍后,我或者其他人在另一个源文件中定义类似的转换。Source2.cpp

#include"Header1.h"
//Define specialization 2
template<>
inline void Foo<int>()
{
 std::cout <<"Specialization 2n";
}
void Function2()
{
 Foo<int>();
}

main.cpp

#include"Header2.h"
#include"Header3.h"
int main()
{
 Function1();
 Function2();
}

问题是如何打印 Function1() 和 Function2()?答案是未定义的行为。

我希望在输出中看到:专门化 1专用 2

但我看到:专门化 2专门化 2

为什么 C++ 编译器对ODR冲突保持沉默?我宁愿在这种情况下编译失败。

我只找到一个解决办法:在未命名名称空间中定义模板函数。

时间:原作者:0个回答

117 5

由于编译器不需要通过 [basic.def.odr/4] 发出任何内容,因此编译器是静默的,因为它不是必需的:

每个程序应该只包含一个非内联函数或者变量的定义,该定义是在一个废弃语句之外的程序中使用的;没有必要。在程序中,定义可以显式出现,可以在标准或者用户定义库中找到,也可以隐式地定义为一个定义。内联函数或者变量应在每个转换单元中定义,它的中的每个转换单元在被丢弃语句外使用。

原作者:
...