59 FORCEINLINE U &&fget(U &&x) {
60 return std::forward<U>(x);
65 FORCEINLINE
decltype(
auto) fget(std::reference_wrapper<U> x) {
79 template <
typename Tag>
94 return std::forward<L>(l);
110 template <
typename F,
typename... Args>
111 FORCEINLINE
decltype(
auto)
operator()(F &&f, Args &&...args)
const {
112 return detail::fget(std::forward<F>(f))(detail::fget(std::forward<Args>(args))...);
128 template <
typename F,
typename... Args>
129 FORCEINLINE
decltype(
auto)
operator()(F &&f, Args &&...args)
const {
130 return detail::fget(std::forward<F>(f)).operator[](detail::fget(std::forward<Args>(args))...);
135#define CLEF_OPERATION(TAG, OP) \
138 struct TAG : binary_op { \
140 static const char *name() { return AS_STRING(OP); } \
144 template <typename L, typename R> \
145 FORCEINLINE auto operator OP(L &&l, R &&r) \
146 requires(is_any_lazy<L, R>) \
148 return expr<tags::TAG, expr_storage_t<L>, expr_storage_t<R>>{tags::TAG(), std::forward<L>(l), std::forward<R>(r)}; \
152 struct operation<tags::TAG> { \
154 template <typename L, typename R> \
155 FORCEINLINE decltype(auto) operator()(L &&l, R &&r) const { \
156 return detail::fget(std::forward<L>(l)) OP detail::fget(std::forward<R>(r)); \
161 CLEF_OPERATION(plus, +);
162 CLEF_OPERATION(minus, -);
163 CLEF_OPERATION(multiplies, *);
164 CLEF_OPERATION(divides, /);
165 CLEF_OPERATION(greater, >);
166 CLEF_OPERATION(less, <);
167 CLEF_OPERATION(leq, <=);
168 CLEF_OPERATION(geq, >=);
169 CLEF_OPERATION(eq, ==);
174#define CLEF_OPERATION(TAG, OP) \
177 struct TAG : unary_op { \
179 static const char *name() { return AS_STRING(OP); } \
183 template <typename L> \
184 FORCEINLINE auto operator OP(L &&l) \
185 requires(is_any_lazy<L>) \
187 return expr<tags::TAG, expr_storage_t<L>>{tags::TAG(), std::forward<L>(l)}; \
191 struct operation<tags::TAG> { \
193 template <typename L> \
194 FORCEINLINE decltype(auto) operator()(L &&l) const { \
195 return OP detail::fget(std::forward<L>(l)); \
199 CLEF_OPERATION(unaryplus, +);
200 CLEF_OPERATION(negate, -);
201 CLEF_OPERATION(loginot, !);
218 template <
typename C,
typename A,
typename B>
219 FORCEINLINE A
operator()(C
const &c, A
const &a, B
const &b)
const {
220 return detail::fget(c) ? detail::fget(a) : detail::fget(b);
236 template <
typename C,
typename A,
typename B>
237 FORCEINLINE
auto if_else(C &&c, A &&a, B &&b) {
254 template <
typename Tag,
typename... Args>
256 using Arg0 = std::decay_t<std::tuple_element_t<0, std::tuple<Args...>>>;
276 template <
typename Tag,
typename... Args>
277 FORCEINLINE
decltype(
auto)
op_dispatch(std::false_type, Args &&...args) {
Provides some utility functions and type traits for the CLEF library.
Provides a basic lazy expression type for the clef library.
__inline__ auto if_else(C &&c, A &&a, B &&b)
Create a lazy ternary (if-else) expression.
__inline__ auto op_dispatch(std::true_type, Args &&...args)
Dispatch operations containing at least one lazy operand.
constexpr bool supports_partial_eval_of_calls
Controls evaluation behavior of function nodes during partial expression evaluation.
constexpr bool supports_partial_eval_of_subscript
Controls evaluation behavior of subscript operations during partial expression evaluation.
typename detail::expr_storage_impl< T >::type expr_storage_t
Type trait to determine how a type should be stored in an expression tree, i.e. either by reference o...
Macros used in the nda library.
Single node of the expression tree.
Generic operation performed on expression nodes.