为什么不为 C++17 放弃单一定义规则?
Why isn't the one definition rule abandoned for C++17?
引用 C++ 草案 N4713:
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 (9.4.1); 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 15.1, 15.4 and 15.8). An inline function or variable
shall be defined in every translation unit in which it is odr-used
outside of a discarded statement.
在 C++17 之前的 C++ 版本中,我可以通过声明我的函数来绕过这个限制 inline
。 C++17 为变量添加了相同的特性。
此外,在我看来,inline
-关键字除了可以忽略 ODR 之外没有其他用途。
那么,为什么不为 C++17 放弃整个规则?我看不到可以关闭的规则的用途。
代价是您需要在任何使用函数的地方定义 inline
函数。如果需要,只需将整个程序放在一个 .cpp 文件中即可。
ODR 是你需要单独编译的,它仍然有用。
"Turning off" inline
的 ODR 不是免费的:inline
实体的定义必须出现在每个翻译单元中。请注意,这意味着对其定义的任何更改都会导致重新编译使用它的每个编译单元。当该函数是许多/大型项目所依赖的某些库的一部分时,这将特别不愉快。
另一方面, 非 inline
函数仅存在于一个编译单元中,并且在其他地方需要时由链接器通过某个符号引用。遵守 ODR 可保证符号不会产生歧义。
来自cppreference:
One and only one definition of every non-inline function or variable
that is odr-used (see below) is required to appear in the entire
program (including any standard and user-defined libraries). The
compiler is not required to diagnose this violation, but the behavior
of the program that violates it is undefined.
将函数声明为 inline
不会 "ignore" ODR,但它会导致函数的每次出现都是它自己的实体,需要在使用它的每个翻译单元中进行定义。小而显着的差异。 ODR 仍然需要有单独的翻译单元。
inline
既危险又昂贵。
它很昂贵,因为现在每个使用某物的编译单元都取决于该物的定义。所以改变body?重新编译它的每个用户。
这很危险,因为如果两个 inline
定义不一致,您的程序就是 IF-NDR(格式错误,不需要诊断)。
没有inline
,两个定义会导致程序格式错误,但编译器必须提供诊断;通常是硬错误。
inline
关闭那个非常有用的警告。
如果每个编译器都能够将不同 inline
定义的 IF-NDR 转换为诊断错误消息,那么您的情况就会更多。只要证明困难 and/or 未实施,inline
就是一个 "activate unsafe mode!" 选项。将其设置为默认值会适得其反。
引用 C++ 草案 N4713:
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 (9.4.1); 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 15.1, 15.4 and 15.8). An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.
在 C++17 之前的 C++ 版本中,我可以通过声明我的函数来绕过这个限制 inline
。 C++17 为变量添加了相同的特性。
此外,在我看来,inline
-关键字除了可以忽略 ODR 之外没有其他用途。
那么,为什么不为 C++17 放弃整个规则?我看不到可以关闭的规则的用途。
代价是您需要在任何使用函数的地方定义 inline
函数。如果需要,只需将整个程序放在一个 .cpp 文件中即可。
ODR 是你需要单独编译的,它仍然有用。
"Turning off" inline
的 ODR 不是免费的:inline
实体的定义必须出现在每个翻译单元中。请注意,这意味着对其定义的任何更改都会导致重新编译使用它的每个编译单元。当该函数是许多/大型项目所依赖的某些库的一部分时,这将特别不愉快。
非 inline
函数仅存在于一个编译单元中,并且在其他地方需要时由链接器通过某个符号引用。遵守 ODR 可保证符号不会产生歧义。
来自cppreference:
One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.
将函数声明为 inline
不会 "ignore" ODR,但它会导致函数的每次出现都是它自己的实体,需要在使用它的每个翻译单元中进行定义。小而显着的差异。 ODR 仍然需要有单独的翻译单元。
inline
既危险又昂贵。
它很昂贵,因为现在每个使用某物的编译单元都取决于该物的定义。所以改变body?重新编译它的每个用户。
这很危险,因为如果两个 inline
定义不一致,您的程序就是 IF-NDR(格式错误,不需要诊断)。
没有inline
,两个定义会导致程序格式错误,但编译器必须提供诊断;通常是硬错误。
inline
关闭那个非常有用的警告。
如果每个编译器都能够将不同 inline
定义的 IF-NDR 转换为诊断错误消息,那么您的情况就会更多。只要证明困难 and/or 未实施,inline
就是一个 "activate unsafe mode!" 选项。将其设置为默认值会适得其反。