Reputation: 1575
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:
typedef
.class
.throw()
or noexcept
. (This is particularly important since every destructor picks up an implicit noexcept
in C++11.)constexpr
.override
and/or final
.[[noreturn]]
and/or [[nodiscard]]
.[[maybe_unused]]
.[[fallthrough]]
within a function body.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
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:
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