CWG Issue 2300 (original) (raw)

This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 117a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-04-13


2300. Lambdas in multiple definitions

Section: 6.3 [basic.def.odr]Status: CD5Submitter: Robert HaberlachDate: 2016-04-11

[Accepted as a DR at the July, 2019 meeting.]

A lambda expression in two translation units has distinct closure types, because each such expression's type is unique within the program. This results in an issue with the ODR, which requires that the definitions of an entity are identical. For example, if

template void f() {std::function<void()> f = []{};}

appears in two translation units, different specializations offunction's constructor template are called, which violates 6.3 [basic.def.odr] bullet 6.4.

Issue 765 dealt with a similar problem for inline functions, but the issue still remains for templates.

Proposed resolution, April, 2019:

Change 6.3 [basic.def.odr] paragraph 12 as follows:

...Given such an entity named D defined in more than one translation unit, then

or

and

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 (_N4868_.13.8.4 [temp.nondep]), and also to dependent names at the point of instantiation (13.8.3 [temp.dep]). If the definitions of D satisfy all these requirements, then the behavior is as if there were a single definition of D. These requirements also apply to corresponding entities defined within each definition ofD (including the closure types of _lambda-expression_s, but excluding entities defined within default arguments or defualt template arguments of either D or an entity not defined withinD). 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 6.6 [basic.link] still applies to these declarations. In particular, _lambda-expression_s (7.5.6 [expr.prim.lambda]) appearing in the type of D may result in the different declarations having distinct types, and _lambda-expression_s appearng in a default argument of D may still denote different types in different translation units. —_end note_] If the definitions of D do not satisfy these requirements, then thebehavior is undefined. program is ill-formed, no diagnostic required. [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 ofg 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 Xcan sppear in multiple translation units of a valid program; the_lambda-expression_s defined within the default argumeht ofX::h within the definition of X denote the same closure type in each translation unit. —_end example_]