2

Given the following code

#include <type_traits>

int main ()
 {
   std::integral_constant<int, 42> ic;

   [&]{ constexpr int i = ic; (void)i; }();
 }

(the (void)i; is just to avoid a "unused variable" warning) clang++ compile without problem where g++ gives the following error

prog.cc: In lambda function:
prog.cc:7:27: error: '__closure' is not a constant expression
    7 |    [&]{ constexpr int i = ic; (void)i; }();
      |                           ^~

Capturing by value

[=]{ constexpr int i = ic; (void)i; }();

both compilers compile without problem.

The question, as usual, is: who's right? g++ or clang++?

-- EDIT --

As pointed by JVApen, ic isn't defined constexpr; so how can a not-constexpr variable initialize a constexpr variable?

Anyway, the behavior doesn't change defining ic as constexpr

constexpr std::integral_constant<int, 42> ic;

clang++ compile without problem; g++ gives an error capturing by reference.

-- EDIT --

As pointed by Jans, defining ic as constexpr and using aggregate initialization

constexpr std::integral_constant<int, 42> ic{};

both compilers compile without problem.

But without constexpr

std::integral_constant<int, 42> ic{};

g++ gives the usual error.

max66
  • 65,235
  • 10
  • 71
  • 111
  • 2
    I actually would think both are wrong, you never define `ic` as a constexpr, so how can you use it to initialize another `constexpr`? – JVApen Dec 30 '18 at 18:56
  • @JVApen - yes, this is another point that confuse me; anyway, we have the same behaviour also defining `ic` as `constexpr`. – max66 Dec 30 '18 at 19:01
  • 1
    @JVApen, The value is contained in the type. Even for a non-constexpr variable, the conversion is purely dependent on the type. – chris Dec 30 '18 at 19:09
  • 1
    @max66 it does compile if you aggregate initialize `constexpr std::integral_constant ic{}` [here](https://godbolt.org/z/j4J06U) – Jans Dec 30 '18 at 19:16
  • @Jans - interesting; thanks. Added your observation to the question. – max66 Dec 30 '18 at 19:24
  • I believe g++ is correct here. Formally, `int i = ic` invokes ic's `operator int()` which is a non-static member, which will reference the closure's stored member's `this` even if it's not needed. note that looking up the value via the static member works: https://gcc.godbolt.org/z/SZqUIL –  Dec 30 '18 at 20:04
  • In other words, your example is the same a [this](https://gcc.godbolt.org/z/ZjJZ0P), which seems reasonable to fail. –  Dec 30 '18 at 20:26
  • @Frank: I don’t think it’s obvious that “referencing” a non-`constexpr` `this` is forbidden: the usual “can’t use a non-constant” is about [lvalue-to-rvalue conversion](http://eel.is/c++draft/expr.const#4.7). – Davis Herring Dec 31 '18 at 01:13
  • 3
    Related: https://stackoverflow.com/q/53978006/5376789, https://stackoverflow.com/q/44386415/5376789. – xskxzr Dec 31 '18 at 03:57

0 Answers0