逗号运算符使 lambda 表达式成为非 constexpr
comma operator makes lambda expression non-constexpr
根据 [this Q&A] since c++11 comma operator is constexpr capable. According to [this Q&A] constexpr 变量不应被 lambda 捕获,但应在其主体内可用。
这两条规则使得以下代码可以在 clang 中编译:
//Example 1
template <int>
struct Foo {};
int main() {
constexpr int c = 1;
static_cast<void>(Foo<(c, 2)>{});
}
//Example 2
template <int>
struct Foo {};
int main() {
constexpr int c = 1;
auto lambda = []{return c * 2;};
static_cast<void>(Foo<lambda()>{});
}
然而,虽然这两个示例都在 clang 上成功编译(声明了 constexpr lambda 支持,即 -- 8.0.0),但以下代码段没有,我无法想象为什么...有什么想法吗?
template <int>
struct Foo {};
int main() {
constexpr int c = 1;
auto lambda = []{return (c, 2);};
static_cast<void>(Foo<lambda()>{});
}
编译错误:
variable 'c' cannot be implicitly captured in a lambda with no capture-default specified
,这似乎是一个 clang bug
A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (7.1) to x yields a constant expression (8.20) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (7.1) is applied to e, or e is a discarded-value expression.
如评论所述,问题不仅限于逗号运算符,而且对于每个丢弃的表达式,这些表达式都不构成 odr-use,因此必须接受.
这是一个 clang 错误,如果我们看一个更简单的案例:
constexpr int c = 1;
auto lambda = [] {return c,2;};
clang 也认为这种格式错误 (see it live), the lambda is required to capture an automatic variable if it odr-uses it see expr.prim.lambda.capturep8:
An entity is captured if it is captured explicitly or implicitly. An entity captured by a lambda-expression is odr-used in the scope containing the lambda-expression. If *this is captured by a local lambda expression, its nearest enclosing function shall be a non-static member function. If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression. If a lambda-expression captures an entity and that entity is not defined or captured in the immediately enclosing lambda expression or function, the program is ill-formed. ...
根据 [this Q&A] since c++11 comma operator is constexpr capable. According to [this Q&A] constexpr 变量不应被 lambda 捕获,但应在其主体内可用。
这两条规则使得以下代码可以在 clang 中编译:
//Example 1
template <int>
struct Foo {};
int main() {
constexpr int c = 1;
static_cast<void>(Foo<(c, 2)>{});
}
//Example 2
template <int>
struct Foo {};
int main() {
constexpr int c = 1;
auto lambda = []{return c * 2;};
static_cast<void>(Foo<lambda()>{});
}
然而,虽然这两个示例都在 clang 上成功编译(声明了 constexpr lambda 支持,即 -- 8.0.0),但以下代码段没有,我无法想象为什么...有什么想法吗?
template <int>
struct Foo {};
int main() {
constexpr int c = 1;
auto lambda = []{return (c, 2);};
static_cast<void>(Foo<lambda()>{});
}
编译错误:
variable 'c' cannot be implicitly captured in a lambda with no capture-default specified
A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (7.1) to x yields a constant expression (8.20) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (7.1) is applied to e, or e is a discarded-value expression.
如评论所述,问题不仅限于逗号运算符,而且对于每个丢弃的表达式,这些表达式都不构成 odr-use,因此必须接受.
这是一个 clang 错误,如果我们看一个更简单的案例:
constexpr int c = 1;
auto lambda = [] {return c,2;};
clang 也认为这种格式错误 (see it live), the lambda is required to capture an automatic variable if it odr-uses it see expr.prim.lambda.capturep8:
An entity is captured if it is captured explicitly or implicitly. An entity captured by a lambda-expression is odr-used in the scope containing the lambda-expression. If *this is captured by a local lambda expression, its nearest enclosing function shall be a non-static member function. If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression. If a lambda-expression captures an entity and that entity is not defined or captured in the immediately enclosing lambda expression or function, the program is ill-formed. ...