/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_FUNCTIONAL_OVERLOAD_HPP #define RANGES_V3_FUNCTIONAL_OVERLOAD_HPP #include #include #include #include #include #include #include namespace ranges { /// \addtogroup group-functional /// @{ /// \cond namespace detail { struct _id { template using invoke = T; }; struct _ref { template using invoke = T &; }; struct _cref { template using invoke = T const &; }; template struct _bind_front { template using invoke = invoke_result_t; }; } // namespace detail /// \endcond template struct overloaded; template<> struct overloaded<> { private: template friend struct overloaded; template using _result_t = void; }; template struct overloaded { private: template friend struct overloaded; RANGES_NO_UNIQUE_ADDRESS First first_; RANGES_NO_UNIQUE_ADDRESS overloaded second_; template using _result_first = detail::_bind_front>; template struct _result_second { template using invoke = typename overloaded ::template _result_t; }; template using _result_t = meta::invoke< meta::conditional_t< (bool) invocable, Args...>, _result_first, _result_second>, Args...>; public: overloaded() = default; constexpr overloaded(First first, Rest... rest) : first_(static_cast(first)) , second_{static_cast(rest)...} {} template(typename... Args)( requires invocable) constexpr _result_t operator()(Args &&... args) && { return invoke((First &&) first_, (Args &&) args...); } template(typename... Args)( requires (!invocable) AND invocable, Args...>) constexpr _result_t operator()(Args &&... args) && { return invoke((overloaded &&) second_, (Args &&) args...); } template(typename... Args)( requires invocable) constexpr _result_t operator()(Args &&... args) & { return invoke(first_, (Args &&) args...); } template(typename... Args)( requires (!invocable) AND invocable &, Args...>) constexpr _result_t operator()(Args &&... args) & { return invoke(second_, (Args &&) args...); } template(typename... Args)( requires invocable) constexpr _result_t operator()(Args &&... args) const & { return invoke(first_, (Args &&) args...); } template(typename... Args)( requires (!invocable) AND invocable const &, Args...>) constexpr _result_t operator()(Args &&... args) const & { return invoke(second_, (Args &&) args...); } }; struct overload_fn { template constexpr Fn operator()(Fn fn) const { return fn; } template constexpr overloaded operator()(Fns... fns) const { return overloaded{static_cast(fns)...}; } }; /// \ingroup group-functional /// \sa `overload_fn` RANGES_INLINE_VARIABLE(overload_fn, overload) /// @} } // namespace ranges #include #endif