1 // Testcase from P0170R1 2 // { dg-options -std=c++17 } 3 4 auto monoid = [](auto v) { return [=] { return v; }; }; 5 auto add = [](auto m1) constexpr { 6 auto ret = m1(); 7 return [=](auto m2) mutable { 8 auto m1val = m1(); 9 auto plus = [=] (auto m2val) mutable constexpr 10 { return m1val += m2val; }; 11 ret = plus(m2()); 12 return monoid(ret); 13 }; 14 }; 15 main()16int main() 17 { 18 constexpr auto zero = monoid(0); 19 constexpr auto one = monoid(1); 20 static_assert(add(one)(zero)() == one()); // OK 21 // Since 'two' below is not declared constexpr, an evaluation of its constexpr 22 // member function call operator can not perform an lvalue-to-rvalue conversion 23 // on one of its subobjects (that represents its capture) in a constant 24 // expression. 25 auto two = monoid(2); 26 if (!(two() == 2)) __builtin_abort(); // OK, not a constant expression. 27 static_assert(add(one)(one)() == two()); // { dg-error "|in .constexpr. expansion of " } two() is not a constant expression 28 static_assert(add(one)(one)() == monoid(2)()); // OK 29 } 30