[SOLVED] Lambda const capture by value bug in msvc?

Issue

This Content is from Stack Overflow. Question asked by doug

This code fails to compile with MSVC but compiles with GCC and CLANG. The problem appears to be that capture by value is not a compile time const.

#include <array>
int main()
{
    const int n = 41;
    auto lambda = [n] {  // Both n and nn should be compile time const
        const int nn {n+1};
        std::array<int,nn> h{};
        return h;
    };
    auto xarray = lambda();
    return xarray.size();
}

Compiler Explorer

Here’s a C++20 standard discussion of lambda value capture showing compile time evaluation:

//[Example 6:
void f1(int i) {
  int const N = 20;
  auto m1 = [=]{
    int const M = 30;
    auto m2 = [i]{
      int x[N][M];          // OK: N and M are not odr-used
      x[0][0] = i;          // OK: i is explicitly captured by m2 and implicitly captured by m1
    };
  };
};

So this is a MSVC bug? Sure looks like it to me.



Solution

MSVC is wrong in rejecting the code(1st snippet) because n is a compile time constant and so nn is also a compile time constant as it is initialized with n.

Note that n inside the lambda body refers to the n outside the lambda and not the member of the closure type because that member is unnamed and isn’t ord-used. This is also described here Why visual c++ (latest) and gcc 12.1 accepted hiding this init capture for lambda, while clang 14.0.0 not? (c++20).

Thus, n is a compile time constant and so is usable in constexpr context. That is, std::array<int, nn> h{}; is valid because nn is a compile time constant as it was initialized by another compile time constant n.


Here is the msvc bug report:

MSVC rejects valid code involving use of constexpr variable as initializer


This Question was asked in StackOverflow by doug and Answered by Jason Liam It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?