{
tree lhs_arg = TREE_VALUE (lhs_bindings);
tree rhs_arg = TREE_VALUE (rhs_bindings);
- gcc_assert (TREE_TYPE (lhs_arg) == TREE_TYPE (rhs_arg));
+ gcc_assert (same_type_p (TREE_TYPE (lhs_arg), TREE_TYPE (rhs_arg)));
if (!cp_tree_equal (lhs_arg, rhs_arg))
return false;
lhs_bindings = TREE_CHAIN (lhs_bindings);
static tree
adjust_temp_type (tree type, tree temp)
{
- if (TREE_TYPE (temp) == type)
+ if (same_type_p (TREE_TYPE (temp), type))
return temp;
/* Avoid wrapping an aggregate value in a NOP_EXPR. */
if (TREE_CODE (temp) == CONSTRUCTOR)
--- /dev/null
+// { dg-do compile { target c++17 } }
+
+#include <utility>
+#include <tuple>
+
+#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");