/* @copyright Louis Dionne 2014 Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) */ #include namespace boost { namespace hana { #if 1 template struct Left { F f; }; template struct Right { F f; }; #define BOOST_HANA_DEFINE_INFIXABLE(OP, OP_CHAR) \ template \ constexpr auto operator OP(X x, Left l) \ { return l.f(x); } \ \ template \ constexpr auto operator OP(Right r, Y y) \ { return r.f(y); } \ /**/ // Arithmetic BOOST_HANA_DEFINE_INFIXABLE(+, '+') BOOST_HANA_DEFINE_INFIXABLE(-, '-') BOOST_HANA_DEFINE_INFIXABLE(*, '*') BOOST_HANA_DEFINE_INFIXABLE(/, '/') BOOST_HANA_DEFINE_INFIXABLE(%, '%') BOOST_HANA_DEFINE_INFIXABLE(&, '&') BOOST_HANA_DEFINE_INFIXABLE(|, '|') BOOST_HANA_DEFINE_INFIXABLE(^, '^') // BOOST_HANA_DEFINE_INFIXABLE(<<, '<<') // BOOST_HANA_DEFINE_INFIXABLE(>>, '>>') // Comparison // BOOST_HANA_DEFINE_INFIXABLE(==, '==') // BOOST_HANA_DEFINE_INFIXABLE(!=, '!=') BOOST_HANA_DEFINE_INFIXABLE(<, '<') // BOOST_HANA_DEFINE_INFIXABLE(<=, '<=') BOOST_HANA_DEFINE_INFIXABLE(>, '>') // BOOST_HANA_DEFINE_INFIXABLE(>=, '>=') // Logical // BOOST_HANA_DEFINE_INFIXABLE(||, '||') // BOOST_HANA_DEFINE_INFIXABLE(&&, '&&') #undef BOOST_HANA_DEFINE_INFIXABLE template struct _inherit : X... { explicit constexpr _inherit(X ...x) : X(x)... { } }; BOOST_HANA_CONSTEXPR_LAMBDA auto inherit = [](auto ...x) { return _inherit{x...}; }; template struct _left { template constexpr auto operator()(F f) const { return Left{f}; } }; template struct _right { template constexpr auto operator()(F f) const { return Right{f}; } }; template constexpr _left left{}; template constexpr _right right{}; template struct _infix { template constexpr auto operator()(F f) const { auto left_to_right = left([=](auto x) { return right([=](auto y) { return f(x, y); }); }); auto right_to_left = right([=](auto y) { return left([=](auto x) { return f(x, y); }); }); return inherit(left_to_right, right_to_left); } }; template constexpr _infix infix{}; #else ////////////////////////////////////////////////////////////////////////////// template struct Infix { F f; template constexpr auto operator()(X ...x) const { return f(x...); } }; template struct PartialInfix { F f; template constexpr auto operator()(X ...x) const { return f(x...); } }; #define BOOST_HANA_DEFINE_INFIX_OPERATOR(LEFT_OP, RIGHT_OP, LEFT, RIGHT) \ template \ constexpr auto operator LEFT_OP(X x, Infix f) { \ auto g = [=](auto y) { return f(x, y); }; \ return PartialInfix{g}; \ } \ \ template \ constexpr auto operator LEFT_OP(X x, PartialInfix f) \ { return f(x); } \ \ template \ constexpr auto operator RIGHT_OP(Infix f, Y y) { \ auto g = [=](auto x) { return f(x, y); }; \ return PartialInfix{g}; \ } \ \ template \ constexpr auto operator RIGHT_OP(PartialInfix f, Y y) \ { return f(y); } \ /**/ BOOST_HANA_DEFINE_INFIX_OPERATOR(*, *, '*', '*'); BOOST_HANA_DEFINE_INFIX_OPERATOR(/, /, '/', '/'); BOOST_HANA_DEFINE_INFIX_OPERATOR(%, %, '%', '%'); BOOST_HANA_DEFINE_INFIX_OPERATOR(+, +, '+', '+'); BOOST_HANA_DEFINE_INFIX_OPERATOR(-, -, '-', '-'); BOOST_HANA_DEFINE_INFIX_OPERATOR(<, >, '<', '>'); BOOST_HANA_DEFINE_INFIX_OPERATOR(>, <, '>', '<'); BOOST_HANA_DEFINE_INFIX_OPERATOR(^, ^, '^', '^'); BOOST_HANA_DEFINE_INFIX_OPERATOR(|, |, '|', '|'); #undef BOOST_HANA_DEFINE_INFIX_OPERATOR template BOOST_HANA_CONSTEXPR_LAMBDA auto infix = [](auto f) { return Infix{f}; }; #endif }} // end namespace boost::hana ////////////////////////////////////////////////////////////////////////////// #include #include #include using namespace boost::hana; BOOST_HANA_CONSTEXPR_LAMBDA auto plus = infix<'/'>(_ + _); BOOST_HANA_CONSTEXPR_LAMBDA auto o = infix<'/'>(compose); int main() { BOOST_HANA_STATIC_ASSERT(1 /plus/ 2 == 3); BOOST_HANA_CONSTEXPR_LAMBDA auto f = [](auto x) { return x % 3; }; BOOST_HANA_CONSTEXPR_LAMBDA auto g = [](auto x) { return x * 2; }; BOOST_HANA_CONSTEXPR_LAMBDA auto h = [](auto x) { return x + 1; }; BOOST_HANA_STATIC_ASSERT((f /o/ g /o/ h)(3) == ((3 + 1) * 2) % 3); // It's better than: BOOST_HANA_STATIC_ASSERT(compose(f, compose(g, h))(3) == ((3 + 1) * 2) % 3); // but it's not better than: // compose(f, g, h)(3) }