为什么C ++链接程序对违反ODR保持沉默? [英] Why C++ linker is silent about ODR violation?

查看:97
本文介绍了为什么C ++链接程序对违反ODR保持沉默?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's consider some synthetic but expressive example. Suppose we have Header.h:

Header1.h

Header1.h

#include <iostream>

// Define generic version
template<typename T>
inline void Foo()
{
    std::cout << "Generic\n";
}

Header2.h

Header2.h

void Function1();

Header3.h

Header3.h

void Function2();

Source1.cpp

Source1.cpp

#include "Header1.h"
#include "Header3.h"

// Define specialization 1
template<>
inline void Foo<int>()
{
    std::cout << "Specialization 1\n";
}

void Function1()
{
    Foo<int>();
}

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

Later I or some else defines similar conversion in another source file. Source2.cpp

#include "Header1.h"

// Define specialization 2
template<>
inline void Foo<int>()
{
    std::cout << "Specialization 2\n";
}

void Function2()
{
    Foo<int>();
}

main.cpp

#include "Header2.h"
#include "Header3.h"

int main()
{
    Function1();
    Function2();
}

问题是什么将打印Function1()和Function2()?答案是不确定的行为.

The question is what will print Function1() and Function2()? The answer is undefined behavior.

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

I expect to see in output: Specialization 1 Specialization 2

但是我看到: 专业化2 专业化2

But I see: Specialization 2 Specialization 2

为什么C ++编译器对违反ODR保持沉默?在这种情况下,我希望编译失败.

Why C++ compilers are silent about ODR violation? I would prefer compilation to be failed in this case.

我只找到一种解决方法:在未命名的命名空间中定义模板函数.

I found only one workaround: define template functions in unnamed namespace.

推荐答案

编译器处于静默状态,因为

The compiler is silent, because it's not required to emit anything by [basic.def.odr/4]:

每个程序应仅包含每个非内联的一个定义 该程序之外的函数或变量 废弃的陈述; 无需诊断.该定义可以 明确显示在程序中,可以在标准或 用户定义的库,或(如果适用)隐式定义 (请参阅[class.ctor],[class.dtor]和[class.copy]).内联函数 或变量应在其所在的每个翻译单元中定义 在废弃的语句之外使用.

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see [class.ctor], [class.dtor] and [class.copy]). An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.

这篇关于为什么C ++链接程序对违反ODR保持沉默?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆