5

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]

11
  • 1
    not an answer but... in wandbox clang++ complain because "variable 'c' cannot be implicitly captured in a lambda with no capture-default specified"; capturing by reference ([&]) complain because "reference to 'c' is not a constant expression"; capturing by value ([=]) compile without problems. The funny part is that g++ compile in all three cases without problem. Commented Nov 22, 2018 at 19:12
  • 2
    I think comma operator takes a reference to c, and references break constexpr Commented Nov 22, 2018 at 19:13
  • 1
    clang bug? I'm not a language layer so, frankly, I don't know. Commented Nov 22, 2018 at 19:18
  • 1
    But works perfectly constexpr auto lambda = []{ auto a=c; return a;};; so no problem with c value but error when c is seen as reference to c? Commented Nov 22, 2018 at 19:25
  • 1
    Just log a bug at bugs.llvm.org for it being different, the one answer seems to indicate that GCC is right Commented Nov 22, 2018 at 21:13

2 Answers 2

5

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.

Sign up to request clarification or add additional context in comments.

Comments

3

This is a clang bug, if we look at a simpler case:

constexpr int c = 1;
auto lambda =  [] {return c,2;};

clang also considers this ill-formed (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. ...

and discarded value expression is not an odr-use.

I found a similar bug report [rejects valid] constexpr non-scalar variable not usable in lambda without capture or local class.

1 Comment

Wow I was sure I tested it without calling lambda too, but appearantly I missed that... So you are probably right that the problem runs deeper...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.