File indexing completed on 2026-07-26 08:22:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include <functional>
0013 #include <type_traits>
0014 #include <utility>
0015
0016 namespace traccc {
0017 template <typename T>
0018 using rvalue_or_const_lvalue = std::disjunction<
0019 std::is_rvalue_reference<T>,
0020 std::conjunction<std::is_lvalue_reference<T>,
0021 std::is_const<std::remove_reference_t<T>>>>;
0022
0023 template <typename T>
0024 class algorithm {};
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template <typename R, typename... A>
0039 class algorithm<R(A...)> {
0040 public:
0041 using output_type = R;
0042
0043 using function_type = R(A...);
0044
0045 static_assert(
0046 std::conjunction<rvalue_or_const_lvalue<A>...>::value,
0047 "All arguments must be either affine types (rvalue references), or "
0048 "immutable constant types (const lvalue references).");
0049
0050 virtual ~algorithm() = default;
0051
0052 virtual output_type operator()(A... args) const = 0;
0053 };
0054
0055 template <typename A, typename B, typename C, typename... R>
0056 auto compose(
0057 std::function<std::remove_const_t<std::remove_reference_t<B>>(A)> f,
0058 std::function<C(B)> g, R... rs) {
0059 if constexpr (sizeof...(R) > 0) {
0060 auto h = compose(g, rs...);
0061 return [f, h](A&& i) { return h(f(std::move(i))); };
0062 } else {
0063 return [f, g](A&& i) { return g(f(std::move(i))); };
0064 }
0065 }
0066
0067 template <typename A, typename B, typename C>
0068 std::function<B(A&&)> side_effect(std::function<B(A)> f,
0069 std::function<void(const C&)> s) {
0070 return [=](A&& i) -> B {
0071 s(i);
0072 return f(std::move(i));
0073 };
0074 }
0075 }