2

I read and reread the relevant clauses about ODR in the C++ standard, but this question still remains open to me. The standard says that the definition of an inline function shall appear in every translation unit in which it is used, and the definitions shall be identical in a sense which is described in almost a page. It says the token sequence must be the same. Does it include the local identifier names?

In other words does the following program violate the ODR? (I tried to test it myself with Visual Studio 2008 and got 0 errors and 0 warnings. But I guess this doesn't prove anything, because I then changed the example to two completely different definitions and still got 0 errors and 0 warnings. In excuse of MSVC it should be noted that no diagnostic is formally required for violations of ODR).

//main.cpp
inline int f(int);
int main(){
   f(3);
}
int f(int x){
   int z = x;
   return z*z;
}

//other.cpp
inline int f(int xx){
   int zz = xx;
   return zz*zz;
}
4

3 回答 3

6

是的,它违反了 ODR。它使用不同的标记序列,因为x它与xx. 就这么简单。尽管它可以有不同的空格或注释,因为它们不是标记。

使用传统的编译工具链来验证跨翻译单元的 ODR 几乎是不可能的。该标准说“不需要诊断”,所以你只会得到未定义的行为。

例如,当您使用在不相关的翻译单元中定义但名称相同的两个不同类时,您可能会遇到更微妙的错误。如果有一个虚拟表,它可能会在没有任何错误消息的情况下发生冲突。因此,请始终为本地函数和类使用匿名命名空间。

于 2010-11-28T15:33:11.550 回答
3

标识符是一种令牌,每个标识符都是一个单独的令牌,所以是的,您需要具有相同的标识符才能尊重 ODR。它可以在检测到这一点的编译器中产生影响(有人准备使用导出的模板为 como 构建示例?它可以检测到一些违反 ODR 的行为)。

那么这里就有C和C++的区别。C 通常没有 ODR,并且 C99 中的内联函数规则(C90 中没有内联函数)与 C++ 的规则完全不同。在 C99 中,您的代码是正确的。事实上,您可以提供完全不同的定义。结果是,在 C 中(但不是在 C++ 中),如果您使用相同的定义并且该定义具有静态成员,那么您实际上拥有与使用该函数的 TU 一样多的静态变量。

于 2010-11-28T16:28:26.333 回答
2

标识符是令牌,因此通过相同的令牌序列规则,程序违反了 ODR。

于 2010-11-28T15:34:11.170 回答