#ifndef BOOST_LAMBDA2_LAMBDA2_HPP_INCLUDED #define BOOST_LAMBDA2_LAMBDA2_HPP_INCLUDED // Copyright 2020, 2021 Peter Dimov // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include #include #include #include #include #include // Same format as BOOST_VERSION: // major * 100000 + minor * 100 + patch #define BOOST_LAMBDA2_VERSION 107800 namespace boost { namespace lambda2 { namespace lambda2_detail { struct subscript { template decltype(auto) operator()(T1&& t1, T2&& t2) const { return std::forward(t1)[ std::forward(t2) ]; } }; template struct get { template decltype(auto) operator()( T&& t ) const { return std::get( std::forward(t) ); } }; } // namespace lambda2_detail // placeholders template struct lambda2_arg { template decltype(auto) operator()( A&&... a ) const noexcept { return std::get( std::tuple( std::forward(a)... ) ); } template auto operator[]( T&& t ) const { return std::bind( lambda2_detail::subscript(), *this, std::forward( t ) ); } }; #if defined(__cpp_inline_variables) && __cpp_inline_variables >= 201606L # define BOOST_LAMBDA2_INLINE_VAR inline #else # define BOOST_LAMBDA2_INLINE_VAR #endif BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<1> _1{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<2> _2{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<3> _3{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<4> _4{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<5> _5{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<6> _6{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<7> _7{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<8> _8{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_arg<9> _9{}; // first, second BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_detail::get<0> first{}; BOOST_LAMBDA2_INLINE_VAR constexpr lambda2_detail::get<1> second{}; #undef BOOST_LAMBDA2_INLINE_VAR } // namespace lambda2 } // namespace boost namespace std { template struct is_placeholder< boost::lambda2::lambda2_arg >: integral_constant { }; } // namespace std namespace boost { namespace lambda2 { namespace lambda2_detail { // additional function objects #define BOOST_LAMBDA2_UNARY_FN(op, fn) \ struct fn \ { \ template decltype(auto) operator()(T&& t) const \ { \ return op std::forward(t); \ } \ }; #define BOOST_LAMBDA2_POSTFIX_FN(op, fn) \ struct fn \ { \ template decltype(auto) operator()(T&& t) const \ { \ return std::forward(t) op; \ } \ }; #define BOOST_LAMBDA2_BINARY_FN(op, fn) \ struct fn \ { \ template decltype(auto) operator()(T1&& t1, T2&& t2) const \ { \ return std::forward(t1) op std::forward(t2); \ } \ }; BOOST_LAMBDA2_BINARY_FN(<<, left_shift) BOOST_LAMBDA2_BINARY_FN(>>, right_shift) BOOST_LAMBDA2_UNARY_FN(+, unary_plus) BOOST_LAMBDA2_UNARY_FN(*, dereference) BOOST_LAMBDA2_UNARY_FN(++, increment) BOOST_LAMBDA2_UNARY_FN(--, decrement) BOOST_LAMBDA2_POSTFIX_FN(++, postfix_increment) BOOST_LAMBDA2_POSTFIX_FN(--, postfix_decrement) BOOST_LAMBDA2_BINARY_FN(+=, plus_equal) BOOST_LAMBDA2_BINARY_FN(-=, minus_equal) BOOST_LAMBDA2_BINARY_FN(*=, multiplies_equal) BOOST_LAMBDA2_BINARY_FN(/=, divides_equal) BOOST_LAMBDA2_BINARY_FN(%=, modulus_equal) BOOST_LAMBDA2_BINARY_FN(&=, bit_and_equal) BOOST_LAMBDA2_BINARY_FN(|=, bit_or_equal) BOOST_LAMBDA2_BINARY_FN(^=, bit_xor_equal) BOOST_LAMBDA2_BINARY_FN(<<=, left_shift_equal) BOOST_LAMBDA2_BINARY_FN(>>=, right_shift_equal) // operators template using remove_cvref_t = std::remove_cv_t>; template> using is_lambda_expression = std::integral_constant::value || std::is_bind_expression::value>; template using enable_unary_lambda = std::enable_if_t::value>; template using enable_binary_lambda = std::enable_if_t::value || is_lambda_expression::value>; template using is_stream = std::is_base_of>; } // namespace lambda2_detail #define BOOST_LAMBDA2_UNARY_LAMBDA(op, fn) \ template> \ auto operator op( A&& a ) \ { \ return std::bind( fn(), std::forward(a) ); \ } #define BOOST_LAMBDA2_POSTFIX_LAMBDA(op, fn) \ template> \ auto operator op( A&& a, int ) \ { \ return std::bind( fn(), std::forward(a) ); \ } #define BOOST_LAMBDA2_BINARY_LAMBDA(op, fn) \ template> \ auto operator op( A&& a, B&& b ) \ { \ return std::bind( fn(), std::forward(a), std::forward(b) ); \ } // standard BOOST_LAMBDA2_BINARY_LAMBDA(+, std::plus<>) BOOST_LAMBDA2_BINARY_LAMBDA(-, std::minus<>) BOOST_LAMBDA2_BINARY_LAMBDA(*, std::multiplies<>) BOOST_LAMBDA2_BINARY_LAMBDA(/, std::divides<>) BOOST_LAMBDA2_BINARY_LAMBDA(%, std::modulus<>) BOOST_LAMBDA2_UNARY_LAMBDA(-, std::negate<>) BOOST_LAMBDA2_BINARY_LAMBDA(==, std::equal_to<>) BOOST_LAMBDA2_BINARY_LAMBDA(!=, std::not_equal_to<>) BOOST_LAMBDA2_BINARY_LAMBDA(>, std::greater<>) BOOST_LAMBDA2_BINARY_LAMBDA(<, std::less<>) BOOST_LAMBDA2_BINARY_LAMBDA(>=, std::greater_equal<>) BOOST_LAMBDA2_BINARY_LAMBDA(<=, std::less_equal<>) BOOST_LAMBDA2_BINARY_LAMBDA(&&, std::logical_and<>) BOOST_LAMBDA2_BINARY_LAMBDA(||, std::logical_or<>) BOOST_LAMBDA2_UNARY_LAMBDA(!, std::logical_not<>) BOOST_LAMBDA2_BINARY_LAMBDA(&, std::bit_and<>) BOOST_LAMBDA2_BINARY_LAMBDA(|, std::bit_or<>) BOOST_LAMBDA2_BINARY_LAMBDA(^, std::bit_xor<>) BOOST_LAMBDA2_UNARY_LAMBDA(~, std::bit_not<>) // additional BOOST_LAMBDA2_UNARY_LAMBDA(+, lambda2_detail::unary_plus) BOOST_LAMBDA2_UNARY_LAMBDA(*, lambda2_detail::dereference) BOOST_LAMBDA2_UNARY_LAMBDA(++, lambda2_detail::increment) BOOST_LAMBDA2_UNARY_LAMBDA(--, lambda2_detail::decrement) BOOST_LAMBDA2_POSTFIX_LAMBDA(++, lambda2_detail::postfix_increment) BOOST_LAMBDA2_POSTFIX_LAMBDA(--, lambda2_detail::postfix_decrement) // compound assignment BOOST_LAMBDA2_BINARY_LAMBDA(+=, lambda2_detail::plus_equal) BOOST_LAMBDA2_BINARY_LAMBDA(-=, lambda2_detail::minus_equal) BOOST_LAMBDA2_BINARY_LAMBDA(*=, lambda2_detail::multiplies_equal) BOOST_LAMBDA2_BINARY_LAMBDA(/=, lambda2_detail::divides_equal) BOOST_LAMBDA2_BINARY_LAMBDA(%=, lambda2_detail::modulus_equal) BOOST_LAMBDA2_BINARY_LAMBDA(&=, lambda2_detail::bit_and_equal) BOOST_LAMBDA2_BINARY_LAMBDA(|=, lambda2_detail::bit_or_equal) BOOST_LAMBDA2_BINARY_LAMBDA(^=, lambda2_detail::bit_xor_equal) BOOST_LAMBDA2_BINARY_LAMBDA(<<=, lambda2_detail::left_shift_equal) BOOST_LAMBDA2_BINARY_LAMBDA(>>=, lambda2_detail::right_shift_equal) // operator<< template::value>, class B, class = lambda2_detail::enable_binary_lambda> auto operator<<( A&& a, B&& b ) { return std::bind( lambda2_detail::left_shift(), std::forward(a), std::forward(b) ); } template::value>, class B, class = lambda2_detail::enable_unary_lambda> auto operator<<( A& a, B&& b ) { return std::bind( lambda2_detail::left_shift(), std::ref(a), std::forward(b) ); } // operator>> template::value>, class B, class = lambda2_detail::enable_binary_lambda> auto operator>>( A&& a, B&& b ) { return std::bind( lambda2_detail::right_shift(), std::forward(a), std::forward(b) ); } template::value>, class B, class = lambda2_detail::enable_unary_lambda> auto operator>>( A& a, B&& b ) { return std::bind( lambda2_detail::right_shift(), std::ref(a), std::forward(b) ); } // operator->* template> auto operator->*( A&& a, B&& b ) { return std::bind( std::forward(b), std::forward(a) ); } } // namespace lambda2 } // namespace boost #endif // #ifndef BOOST_LAMBDA2_LAMBDA2_HPP_INCLUDED