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;
}
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434

3 Answers3

6

Yes, it violates ODR. It uses different token sequences, because x is a different token from xx. It's as simple as that. Though it can have different whitespace or comments, as those aren't tokens.

Verifying ODR across translation units is hard to impossible with traditional compilation toolchain. The standard says that "No diagnostics required", so you just get undefined behavior.

You may get even more subtle errors when you use e.g. two different classes defined in unrelated translation units but with the same name. If there is a virtual table it may clash without any error messages. So always use an anonymous namespaces for local functions and classes.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
3

Identifier is a kind of token, each identifier is a separate token, so yes, you need to have the same identifier to respect the ODR. It can make a difference in a compiler which detect this (someone ready to build an example for como with exported template? it can detect some violation of the ODR).

Then there is a difference between C and C++ here. C doesn't have the ODR in general and the rules for inline function in C99 (there is no inline functions in C90) are quite different to those of C++. In C99, your code is correct. In fact you can provide completely different definition. A consequence is that in C (but not in C++), if you use the same definition and that definition has a static member, you have in fact as many static variables as TU using the function.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • 1
    +1, but maybe you could clarify the last sentence (currently it sounds like it could be describing either C or C++). – j_random_hacker Nov 28 '10 at 17:47
  • 1
    In regard to the static objects in C inline functions, note that the standard says: *"An inline definition of a function with external linkage shall not contain a definition of a modifiable object with static storage duration, and shall not contain a reference to an identifier with internal linkage."* – caf Nov 29 '10 at 01:45
2

Identifiers are tokens, so by the same sequence of tokens rule, the program violates the ODR.

lijie
  • 4,811
  • 22
  • 26