Joshua Green
Joshua Green

Reputation: 1575

inline functions and the one definition rule

inline functions provide something of a weakening of the one definition rule -- multiple definitions are allowed, albeit with some restrictions. One wording I found online is

The requirements are that each definition should be the same, meaning it should consist of the same tokens and refer to the same items.

though I admit that I don't know if that's definitive. I'm also not sure how strict it is.

I'm considering cases in which I create headers with class definitions and/or inline functions that I want to be #include-able whether one is compiling in C++03, C++11, or even some later standard. It would be natural to use the __cplusplus macro to conditionally change the code, but will the ODR come into play? For example, it seems reasonable to conditionally:

but which of these -- if any -- are actually allowed if one wants to enable libraries that #include such headers to be compiled under different standards and still be safely used together?

Upvotes: 3

Views: 697

Answers (1)

Nir Friedman
Nir Friedman

Reputation: 17694

In general, you can't do any of this stuff safely. There's only two ways to safely use say two definitions of a class. Trivially you can simply have two separate processes compiled differently that communicate via e.g. shared memory. Less trivially, you can use two libraries that define the same symbol A in two different way if:

  • the symbol A is only an implementation detail of the library; it cannot be provided by the library nor appear in any interfaces
  • Along these lines, none of the library's header files should transitively include A's header. So client translation units will not receive any definition of A from the library.
  • the visibility of the symbol A must be marked private/hidden.

If you do all that, then A is truly an implementation detail of the library, and you can use multiple libraries that define A differently. If any of these is not satisfied, then you can't guarantee that any of the above will work (though some will).

One of the most surprising outcomes for those not familiar with the linker, is that if lib1 and lib2 both use symbol A, even if they stop any leakage through the headers, if the visibility of A is public then a single definition of A will be used across both libraries. So either lib2 will use lib1's definition, or vice versa. This can rather easily lead to UB.

On *nix systems, public visibilility is the default so you will need to be sure to go out of your way to hide the symbol, which is a bit arcane.

Upvotes: 1

Related Questions