This boils down to the fact that the lambda type is different from translation units. If so, this can affect the output of the template argument and potentially call the different functions that should be called - in what should be sequential definitions. This will violate ODR (see below).
However, this is not intended. In fact, this problem has long been affected by the main problem 765 , which specifically specifies built-in functions with external communication - for example, f :
7.1.2 [dcl.fct.spec] paragraph 4 indicates that local static variables and string literals appearing in the body of an inline function with an external link must be the same entity in each translation unit in the program. Nothing is said, however, about whether local types should also be the same.
Although the corresponding program could always determine this using typeid, recent changes in C ++ ( allowing local types to be used as templates for type arguments, closing classes for lambda expressions ) make this question more pressing.
Notes for the July 2009 meeting:
Types must be the same.
The resolution now included the following wording in [dcl.fct.spec] / 4 :
The type defined inside the body of the extern inline function is the same type in each translation unit.
(NB: MSVC does not yet refer to the above wording, although it may be in a future release ).
Thus, Lambdas inside such function bodies is safe, since the definition of the type of closure is really in the block area (
[expr.prim.lambda] / 3 ) <w> Therefore, several definitions of
f have always been clearly defined.
This resolution, of course, does not cover all scenarios, since there are many other types of entities with external communication that can use lambdas, in particular, function templates - this should be covered by another main problem.
Meanwhile, Itanium already contains the appropriate rules to ensure that these types of lambda match in more situations, so Clang and GCC should basically behave as intended.
Standard information on why various types of faults are an ODR violation. Consider the bullet points (6.2) and (6.4) in [basic.def.odr] / 6 :
There may be more than one definition [...]. For such an object with the name D defined in several translation units, each definition of D should consist of the same sequence of tokens; and
(6.2) - in each definition of D , the corresponding names scanned according to [basic.lookup], refers to the entity defined in the definition of D or should refer to the same object after ([over.match]) and after negotiating a partial template specialization ( [temp.over]), [...]; and
(6.4) - in each definition of D overloaded operators in question, implicit calls to transformation functions , constructors , new operator functions and operator removal functions must refer to the same function or function defined in the definition of D ; [...]
This effectively means that any functions called in the definition of an entity must be the same in all units of a translation - or have been defined inside its definition , as well as local classes and their members. That is, the use of lambda as such is not problematic, but it is clear that there is a transfer of it to functional templates, since they are defined outside the definition.
In your C example, the type of closure is defined inside the class (whose scope is the least encompassing). If the type of closure differs in two TUs that the standard may inadvertently imply with the uniqueness of the type of closure, the constructor creates an instance and invokes various specializations of the function constructor template, violating (6.4) in the above quote.