--- /dev/null
+// PR c++/69066
+// { dg-do compile { target c++14 } }
+
+template <typename T> T&& declval();
+
+template<typename T, T v>
+struct integral_constant
+{
+ static constexpr T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+ constexpr operator value_type() const { return value; }
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template <typename...>
+using void_t = void;
+
+template <typename, typename = void>
+class is_zero_callable : public false_type
+{
+};
+
+template <typename T>
+class is_zero_callable<T, void_t<decltype(declval<T>()())>>
+ : public true_type
+{
+};
+
+template <typename TF, bool TLastStep>
+struct curry_impl
+{
+ static auto exec(TF f)
+ {
+ // Bind `x` to subsequent calls.
+ return [=](auto x)
+ {
+ auto bound_f = [=](auto... xs) -> decltype(f(x, xs...))
+ {
+ return f(x, xs...);
+ };
+
+ // Recursive step.
+ return curry_impl<decltype(bound_f),
+ is_zero_callable<decltype(bound_f)>{}>::exec(bound_f);
+ };
+ }
+};
+
+template <typename TF>
+struct curry_impl<TF, true>
+{
+ static auto exec(TF f)
+ {
+ return f();
+ }
+};
+
+template <typename TF>
+auto curry(TF f)
+{
+ return curry_impl<TF, is_zero_callable<decltype(f)>{}>::exec(f);
+}
+
+int main()
+{
+ auto sum = [](int x, int y)
+ {
+ return x + y;
+ };
+
+ (void)curry(sum)(1)(1);
+}