Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

comma operator makes lambda expression non-constexpr

According to [this Q&A] since c++11 comma operator is constexpr capable. According to [this Q&A] constexpr variable should not be captured by lambda but should be usable inside its body.

Both these rules make following code compilable in 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()>{});
}

However while both these examples compile successfully on clang (that declares constexpr lambda support that is -- 8.0.0) the following snippet doesn't and I can't imagine why... Any ideas?

template <int>
struct Foo {};

int main() {
    constexpr int c = 1;
    auto lambda = []{return (c, 2);};
    static_cast<void>(Foo<lambda()>{});
}

Compilation error:

variable 'c' cannot be implicitly captured in a lambda with no capture-default specified

[live demo]

like image 337
W.F. Avatar asked Nov 22 '18 18:11

W.F.


1 Answers

Its seems to be a clang bug, according to [basic.def.odr]/4:

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.

As has been commented, the issue is not limited to the comma operator but for every discarded expressions, these expression doesn't constitute odr-use, hence it must be accepted.

like image 161
Jans Avatar answered Sep 28 '22 08:09

Jans