0

Code first, we have the following piece of code that is used to accumulate a constexpr std::array in compile time:

template <typename T, std::size_t N, typename O>
constexpr T compile_time_accumulator(const std::array<T, N> const &A, const std::size_t i, const O& op, const T initialValue)
{
  return (i < N)
       ? op(A[i], compile_time_accumulator(A, i + 1, op, initialValue))
       : initialValue;
}

and the following code example to test/varify it (i.e., that it evaluates in compile time):

constexpr std::array<int, 4> v {{4, 5, 6, 7}};
std::cout << std::integral_constant<int, compile_time_accumulator(v, 42, std::plus<int>())>::value 
          << std::endl;

LIVE DEMO

Now if change the operator std::plus<int> with a constexpr lambda:

constexpr auto lambda_plus = [] (int x, int y) { return x + y; };

and call it like below:

constexpr std::array<int, 4> v {{4, 5, 6, 7}};
std::cout << std::integral_constant<int, compile_time_accumulator(v, 42, lambda_plus)>::value << std::endl;
                                                                         ^^^^^^^^^^^ 

I get an error, that lambda is not constexpr :

call to non-constexpr function ''

Now doing a litle research I discovered that constexpr lambdas aren't support yet.

Q:

Why if constexpr lambdas aren't supported, we are allowed to define a constexpr lambda in the first place?

Edit:

It seems that clang doesn't accep the code. So which compiler is right?

Cœur
  • 37,241
  • 25
  • 195
  • 267
101010
  • 41,839
  • 11
  • 94
  • 168

2 Answers2

3

C++11 allowed a very limited amount definition of a constexpr while C++14 has a long list of is not a constexpr

From n4296 (release candidate for C++14) 5.20.2.6

5.20 Constant expressions [expr.const]

2 A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:

2.6) — a lambda-expression (5.1.2);

So the answer is that lambda's are not OK so the compiler must be wrong.

user1
  • 4,031
  • 8
  • 37
  • 66
Surt
  • 15,501
  • 3
  • 23
  • 39
  • Yeap seems you're right clang complains about them [code](http://coliru.stacked-crooked.com/a/bccb610676dbb818). – 101010 Oct 15 '15 at 22:18
  • @101010 Hello (again ;) ), you'll notice that [if you compile with `-std=c++11`](http://coliru.stacked-crooked.com/a/7a324c1a5a8a2cbb), both gcc and clang don't allow `std::plus()`... Perhaps the _`constexpr`ness_ of `std::plus::operator()` has been added only since `C++14` (I haven't checked the standard but [cppreference](http://en.cppreference.com/w/cpp/utility/functional/plus) and [cplusplus.com](http://www.cplusplus.com/reference/functional/plus/) don't seem to give similar info on that matter) – maddouri Oct 16 '15 at 09:35
3

The code is indeed ill-formed as per [expr.const]/(2.6); lambdas aren't yet allowed in constant expressions, though a corresponding proposal is in circulation. GCC is incorrect in accepting lambda_plus's declaration.

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • Yeap seems you're right clang complains about them [code](http://coliru.stacked-crooked.com/a/bccb610676dbb818). – 101010 Oct 15 '15 at 22:18