[basic.def.odr] (original) (raw)

6 Basics [basic]

6.3 One-definition rule [basic.def.odr]

No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, template, default argument for a parameter (for a function in a given scope), or default template argument.

An expression or conversion is potentially evaluated unless it is an unevaluated operand ([expr.prop]), a subexpression thereof, or a conversion in an initialization or conversion sequence in such a context.

The set of potential results of an expression E is defined as follows:

[ Note

:

This set is a (possibly-empty) set of id-expressions, each of which is either E or a subexpression of E.

[ Example

:

In the following example, the set of potential results of the initializer of n contains the first S​::​x subexpression, but not the secondS​::​x subexpression.

struct S { static const int x = 0; }; const int &f(const int &r); int n = b ? (1, S::x)
: f(S::x);

end example

]

end note

]

A function is named byan expression or conversion as follows:

A variable x whose name appears as a potentially-evaluated expression Eis odr-used by E unless

A structured binding is odr-used if it appears as a potentially-evaluated expression.

*this is odr-used if this appears as a potentially-evaluated expression (including as the result of the implicit transformation in the body of a non-static member function ([class.mfct.non-static])).

A virtual member function is odr-used if it is not pure.

A function is odr-used if it is named by a potentially-evaluated expression or conversion.

A non-placement allocation or deallocation function for a class is odr-used by the definition of a constructor of that class.

A non-placement deallocation function for a class is odr-used by the definition of the destructor of that class, or by being selected by the lookup at the point of definition of a virtual destructor ([class.dtor]).20

An assignment operator function in a class is odr-used by an implicitly-defined copy-assignment or move-assignment function for another class as specified in [class.copy.assign].

A constructor for a class is odr-used as specified in [dcl.init].

A local entity ([basic.pre]) is odr-usable in a declarative region ([basic.scope.declarative]) if:

If a local entity is odr-used in a declarative region in which it is not odr-usable, the program is ill-formed.

[ Example

:

void f(int n) { [] { n = 1; };
struct A { void f() { n = 2; }
}; void g(int = n);
[=](int k = n) {};

[&] { [n]{ return n; }; };
}

end example

]

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required.

[ Example

:

auto f() { struct A {}; return A{}; } decltype(f()) g(); auto x = g();

A program containing this translation unit is ill-formed because g is odr-used but not defined, and cannot be defined in any other translation unit because the local class A cannot be named outside this translation unit.

end example

]

A definition of an inline function or variable shall be reachable from the end of every definition domain in which it is odr-used outside of a discarded statement.

A definition of a class is required to be reachable in every context in which the class is used in a way that requires the class type to be complete.

[ Example

:

The following complete translation unit is well-formed, even though it never defines X:

struct X;
struct X* x1;
X* x2;

end example

]

[ Note

:

The rules for declarations and expressions describe in which contexts complete class types are required.

A class type T must be complete if:

end note

]

There can be more than one definition of a

in a program provided that each definition appears in a different translation unit and the definitions satisfy the following requirements.

Given such an entity D defined in more than one translation unit, for all definitions of D, or, if D is an unnamed enumeration, for all definitions of D that are reachable at any given program point, the following requirements shall be satisfied.

end example
]

If D is a template and is defined in more than one translation unit, then the preceding requirements shall apply both to names from the template's enclosing scope used in the template definition ([temp.nondep]), and also to dependent names at the point of instantiation ([temp.dep]).

These requirements also apply to corresponding entities defined within each definition of D(including the closure types of lambda-expressions, but excluding entities defined within default arguments or default template arguments of either D or an entity not defined within D).

For each such entity and for D itself, the behavior is as if there is a single entity with a single definition, including in the application of these requirements to other entities.

[ Note

:

The entity is still declared in multiple translation units, and [basic.link]still applies to these declarations.

In particular,lambda-expressionsappearing in the type of D may result in the different declarations having distinct types, andlambda-expressions appearing in a default argument of Dmay still denote different types in different translation units.

end note

]

If these definitions do not satisfy these requirements, then the program is ill-formed; a diagnostic is required only if the entity is attached to a named module and a prior definition is reachable at the point where a later definition occurs.

[ Example

:

inline void f(bool cond, void (*p)()) { if (cond) f(false, []{}); } inline void g(bool cond, void (*p)() = []{}) { if (cond) g(false); } struct X { void h(bool cond, void (*p)() = []{}) { if (cond) h(false); } };

If the definition of f appears in multiple translation units, the behavior of the program is as if there is only one definition of f.

If the definition of g appears in multiple translation units, the program is ill-formed (no diagnostic required) because each such definition uses a default argument that refers to a distinct lambda-expression closure type.

The definition of X can appear in multiple translation units of a valid program; the lambda-expressions defined within the default argument of X​::​h within the definition of Xdenote the same closure type in each translation unit.

end example

]

If, at any point in the program, there is more than one reachable unnamed enumeration definition in the same scope that have the same first enumerator name and do not have typedef names for linkage purposes ([dcl.enum]), those unnamed enumeration types shall be the same; no diagnostic required.