【问题标题】:Non-overloadable non-inline function definitions in different translation units不同翻译单元中不可重载的非内联函数定义
【发布时间】:2020-02-25 20:11:22
【问题描述】:
假设我有 2 个 TU,其中 2 个具有外部链接的非内联函数定义,它们仅在返回类型上有所不同。
我的程序违反了哪一段?
[basic.def.odr]/4 说:
每个程序都应包含一个定义,即在该程序中被丢弃的语句之外的每个非内联函数或变量的定义;无需诊断。
但是
- 这一段说“那是 odr-used” 这可能是也可能不是。
- 毕竟,我如何判断我是否在不同的 TU 中定义了相同的非内联函数? [over.dcl]/1 说的是同一个范围。
【问题讨论】:
标签:
c++
c++17
language-lawyer
one-definition-rule
【解决方案1】:
相信你在找:[basic.link]/9:
如果两个名称相同([basic.pre])并且在不同的范围内声明,则应表示相同的变量、函数、类型、模板或命名空间
- 两个名称都具有外部或模块链接,并在附加到同一模块的声明中声明,或者两个名称都具有内部链接并在同一翻译单元中声明;和
- 两个名称都指同一命名空间的成员或同一类的成员,而不是通过继承;和
- 当两个名称都表示函数或函数模板时,签名([defns.signature]、[defns.signature.templ])是相同的。
如果多个具有外部链接的同名声明将声明相同的实体,但它们附加到不同的模块,则程序格式错误;不需要诊断。 [注意:using-declarations、typedef 声明和 alias-declarations 不声明实体,而只是引入同义词。同样,使用指令不声明实体。 ——尾注]
还有[basic.link]/11:
在所有类型调整之后(在此期间 typedef 被其定义替换),引用给定变量或函数的所有声明指定的类型应相同,但数组对象的声明可以指定不同的数组类型是否存在主要数组绑定 ([dcl.array])。在类型标识上违反此规则不需要诊断。
还有[defns.signature]:
⟨function⟩名称、参数类型列表([dcl.fct])和封闭命名空间(如果有)
返回类型不是签名的一部分,因此您违反了相同签名意味着相同实体的规则。
一般来说,在 Davis “我们不配的英雄” Herring 的作品通过之前,标准中关于范围和名称查找的所有讨论都非常失败。