| 385 | namespace _impl_ { |
| 386 | |
| 387 | template <auto op, typename... Args> struct Expr { |
| 388 | template <typename Runtime> |
| 389 | using Eval = decltype(op(typename Args::template Eval<Runtime>{}...)); |
| 390 | |
| 391 | #define UN_OP(O) \ |
| 392 | constexpr auto operator O() const noexcept { \ |
| 393 | return Expr<[](auto self) { return O self; }, Expr<op, Args...>>{}; \ |
| 394 | } |
| 395 | #define POST_UN_OP(O) \ |
| 396 | constexpr auto operator O##O(int) const noexcept { \ |
| 397 | return Expr<[](auto self) { return self O##O; }, Expr<op, Args...>>{}; \ |
| 398 | } |
| 399 | #define BIN_OP(O) \ |
| 400 | template <typename Rhs> constexpr auto operator O(Rhs) const noexcept { \ |
| 401 | return Expr<[](auto self, auto rhs) { return (self O rhs); }, \ |
| 402 | Expr<op, Args...>, Rhs>{}; \ |
| 403 | } |
| 404 | #define POLY_OP(O) \ |
| 405 | template <typename... Rhs> \ |
| 406 | constexpr auto operator O(Rhs...) const noexcept { \ |
| 407 | return Expr<[](auto self, auto... rhs) { \ |
| 408 | return self.operator O(rhs...); \ |
| 409 | }, \ |
| 410 | Expr<op, Args...>, Rhs...>{}; \ |
| 411 | } |
| 412 | #include "ops.inc" |
| 413 | }; |
| 414 | |
| 415 | constexpr auto id = [](auto x) { return x; }; |
| 416 | template <typename E> static constexpr auto expr = Expr<id, E>{}; |
nothing calls this directly
no outgoing calls
no test coverage detected