Reputation: 49251
I've encountered a strange problem that kind of breaks what I understand about a compilation unit's encapsulation.
In a nutshell I have a common inlined function that I get from a header.
I include that into 2 different .cpp files, with a different #define
macros.
But I end up getting the same implementation in bot compilation units.
Common.h:
#include <iostream>
inline void printA()
{
#ifdef YES
std::cout << " yes" << std::endl;
#else
std::cout << " no" << std::endl;
#endif
}
File1.h:
void print1();
File1.cpp:
#define YES
#include "Common.h"
#include "File1.h"
void print1()
{
printA();
}
File2.h:
void print2();
File2.cpp
#include "Common.h"
#include "File2.h"
void print2()
{
printA();
}
main.cpp:
#include "File1.h"
#include "File2.h"
int main(int argc, char* argv[])
{
print1();
print2();
return 0;
}
The output to this example is:
yes
yes
I would expect it to be:
yes
no
So, why is the same implementation taken in both compilation units ?
The common function is even inlined....
How can I get my "expected" result?
And, why is the "yes" implementation chosen ? Just a matter of compilation order?
BTW, I get the same results on GCC 4.8 and VS2012
Upvotes: 2
Views: 249
Reputation: 92271
The standard (here N4527) says in 3.2 One definition rule/6
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then (6.1)
— each definition of D shall consist of the same sequence of tokens; and
...
If the definitions of D satisfy all these requirements, then the behavior is as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.
So replacing "yes" with "no" is an ODR-violation, causing undefined behavior.
For the result of getting "yes" I can guess that the compiler picks one function at random, as they have to be identical.
On the other hand, if you made the function static
, you would have different local functions in each translation unit.
Upvotes: 3