111
|
1 // PR c++/69066
|
|
2 // { dg-do compile { target c++14 } }
|
|
3
|
|
4 template <typename T> T&& declval();
|
|
5
|
|
6 template<typename T, T v>
|
|
7 struct integral_constant
|
|
8 {
|
|
9 static constexpr T value = v;
|
|
10 typedef T value_type;
|
|
11 typedef integral_constant<T, v> type;
|
|
12 constexpr operator value_type() const { return value; }
|
|
13 };
|
|
14
|
|
15 typedef integral_constant<bool, true> true_type;
|
|
16 typedef integral_constant<bool, false> false_type;
|
|
17
|
|
18 template <typename...>
|
|
19 using void_t = void;
|
|
20
|
|
21 template <typename, typename = void>
|
|
22 class is_zero_callable : public false_type
|
|
23 {
|
|
24 };
|
|
25
|
|
26 template <typename T>
|
|
27 class is_zero_callable<T, void_t<decltype(declval<T>()())>>
|
|
28 : public true_type
|
|
29 {
|
|
30 };
|
|
31
|
|
32 template <typename TF, bool TLastStep>
|
|
33 struct curry_impl
|
|
34 {
|
|
35 static auto exec(TF f)
|
|
36 {
|
|
37 // Bind `x` to subsequent calls.
|
|
38 return [=](auto x)
|
|
39 {
|
|
40 auto bound_f = [=](auto... xs) -> decltype(f(x, xs...))
|
|
41 {
|
|
42 return f(x, xs...);
|
|
43 };
|
|
44
|
|
45 // Recursive step.
|
|
46 return curry_impl<decltype(bound_f),
|
|
47 is_zero_callable<decltype(bound_f)>{}>::exec(bound_f);
|
|
48 };
|
|
49 }
|
|
50 };
|
|
51
|
|
52 template <typename TF>
|
|
53 struct curry_impl<TF, true>
|
|
54 {
|
|
55 static auto exec(TF f)
|
|
56 {
|
|
57 return f();
|
|
58 }
|
|
59 };
|
|
60
|
|
61 template <typename TF>
|
|
62 auto curry(TF f)
|
|
63 {
|
|
64 return curry_impl<TF, is_zero_callable<decltype(f)>{}>::exec(f);
|
|
65 }
|
|
66
|
|
67 int main()
|
|
68 {
|
|
69 auto sum = [](int x, int y)
|
|
70 {
|
|
71 return x + y;
|
|
72 };
|
|
73
|
|
74 (void)curry(sum)(1)(1);
|
|
75 }
|