diff gcc/testsuite/g++.dg/cpp1z/pr85569.C @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/testsuite/g++.dg/cpp1z/pr85569.C	Thu Feb 13 11:34:05 2020 +0900
@@ -0,0 +1,94 @@
+// { dg-do compile { target c++17 } }
+
+#include <utility>
+#include <tuple>
+#include <functional>
+
+#define LIFT_FWD(x) std::forward<decltype(x)>(x)
+
+template <typename T>
+inline
+constexpr
+auto
+equal(
+  T &&t)
+{
+  return [t = std::forward<T>(t)](const auto& obj)
+    -> decltype(obj == t)
+    {
+      return obj == t;
+    };
+}
+
+template <typename F, typename T>
+struct is_tuple_invocable;
+
+template <typename F, typename ... Ts>
+struct is_tuple_invocable<F, std::tuple<Ts...>>
+{
+  using type = typename std::is_invocable<F, Ts...>::type;
+};
+
+template <typename F>
+inline
+constexpr
+auto
+compose(
+  F&& f
+)
+  noexcept
+-> F
+{
+  return std::forward<F>(f);
+}
+
+namespace detail {
+  template <typename F, typename Tail, typename ... T>
+  inline
+  constexpr
+  auto
+  compose(
+    std::true_type,
+    F&& f,
+    Tail&& tail,
+    T&& ... objs)
+  noexcept(noexcept(f(tail(std::forward<T>(objs)...))))
+  -> decltype(f(tail(std::forward<T>(objs)...)))
+  {
+    return f(tail(std::forward<T>(objs)...));
+  }
+}
+template <typename F, typename ... Fs>
+inline
+constexpr
+auto
+compose(
+  F&& f,
+  Fs&&... fs)
+{
+  return [f = std::forward<F>(f), tail = compose(std::forward<Fs>(fs)...)]
+    (auto&& ... objs)
+    -> decltype(detail::compose(typename std::is_invocable<decltype(compose(std::forward<Fs>(fs)...)), decltype(objs)...>::type{},
+                                f,
+                                compose(std::forward<Fs>(fs)...),
+                                LIFT_FWD(objs)...))
+  {
+    using tail_type = decltype(compose(std::forward<Fs>(fs)...));
+    
+#ifndef NOT_VIA_TUPLE
+    using args_type = std::tuple<decltype(objs)...>;
+    constexpr auto unitail = typename is_tuple_invocable<tail_type, args_type>::type{};
+#else
+    constexpr auto unitail = typename std::is_invocable<tail_type, decltype(objs)...>::type{};
+#endif
+
+    return detail::compose(unitail,  f, tail, LIFT_FWD(objs)...);
+  };
+}
+
+template <auto N>
+constexpr auto eq = equal(N);
+
+static_assert(compose(eq<3>,
+		      std::plus<>{})(1,2),
+              "compose is constexpr");