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()16 int 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