-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong
Reference (section label): basic.def.odr
Link to reflector thread (if any): N/A
Issue description:
https://eel.is/c++draft/basic.def.odr#10 defines odr-usable and has a rule:
If a local entity is odr-used in a scope in which it is not odr-usable, the program is ill-formed.
One of the requirements for a local entity to be odr-usable, is that there are no intervening scopes other than block scopes and function parameter scopes.
Consider:
void f() {
int x;
[&] { return x; };
}
There is a lambda scope (https://eel.is/c++draft/basic.scope.lambda) between the block scope of the compound-statement and the definition of x
. It follows that the above code is ill-formed (according to the wording).
Consider also:
struct A {
A() = default;
A(const A &) = delete;
constexpr operator int() { return 42; }
};
void f() {
constexpr A a;
[=]<typename T, int = a> {};
}
The only reason from the wording for why a
is not odr-usable from the default argument (and thus not captured, see https://eel.is/c++draft/expr.prim.lambda.capture#7) is because there is a lambda scope. There is implementation divergence: https://godbolt.org/z/d41381qxM. Behaviours observed include accepting the code, rejecting the code because of the deleted copy constructor, and rejecting the code because a
is named from the default template argument.
Suggested resolution:
Replace the bullets under https://eel.is/c++draft/basic.def.odr#10.2 with:
- the intervening scope is a block scope,
- the intervening scope is the function parameter scope of a lambda-expression, or
- the intervening scope is the lambda scope of a lambda-expression that has a simple-capture naming the entity or has a capture-default, and the block scope of the lambda-expression is also an intervening scope.