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; value_typeintegral_constant12 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 { execcurry_impl35 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 } 76