| // Copyright Daniel Wallin 2006. |
| // Copyright Cromwell D. Enage 2017. |
| // Distributed under 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) |
| |
| #ifndef BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_CAST_HPP |
| #define BOOST_PARAMETER_AUX_PREPROCESSOR_IMPL_FUNCTION_CAST_HPP |
| |
| #include <boost/parameter/config.hpp> |
| |
| #if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING) |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| // Handles possible implicit casts. Used by preprocessor.hpp |
| // to normalize user input. |
| // |
| // cast<void*>::execute() is identity |
| // cast<void*(X)>::execute() is identity |
| // cast<void(X)>::execute() casts to X |
| // |
| // preprocessor.hpp uses this like this: |
| // |
| // #define X(value, predicate) |
| // cast<void predicate>::execute(value) |
| // |
| // X(something, *) |
| // X(something, *(predicate)) |
| // X(something, (int)) |
| template <typename VoidExpr, typename Args> |
| struct cast; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/parameter/aux_/use_default_tag.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename T, typename B> |
| inline ::boost::parameter::aux::use_default_tag |
| forward(::boost::parameter::aux::use_default_tag) |
| { |
| return ::boost::parameter::aux::use_default_tag(); |
| } |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/if.hpp> |
| |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #include <boost/mp11/integral.hpp> |
| #include <boost/mp11/utility.hpp> |
| #endif |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Args> |
| struct cast<void*,Args> |
| { |
| template <typename T, typename B> |
| struct apply |
| { |
| typedef typename ::boost::mpl |
| ::if_<B,T,::boost::mpl::true_>::type type; |
| }; |
| |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| template <typename T, typename B> |
| using fn = ::boost::mp11::mp_if<B,T,::boost::mp11::mp_true>; |
| #endif |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/parameter/aux_/void.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Predicate, typename Args> |
| struct cast<void*(Predicate),Args> |
| : ::boost::parameter::aux::cast<void*,Args> |
| { |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/mpl/placeholders.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| // This is a hack used in cast<> to turn the user supplied type, |
| // which may or may not be a placeholder expression, into one, |
| // so that it will be properly evaluated by mpl::apply. |
| template <typename T, typename Dummy = ::boost::mpl::_1> |
| struct as_placeholder_expr |
| { |
| typedef T type; |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #include <boost/mp11/list.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Target, typename Source, typename Args> |
| struct apply_target_fn |
| { |
| using type = ::boost::mp11 |
| ::mp_apply_q<Target,::boost::mp11::mp_list<Source,Args> >; |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #endif |
| |
| #include <boost/mpl/apply.hpp> |
| |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #include <boost/parameter/aux_/has_nested_template_fn.hpp> |
| #include <type_traits> |
| #else |
| #include <boost/type_traits/is_same.hpp> |
| #include <boost/type_traits/remove_const.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| #endif |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Target, typename Source, typename Args> |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| using is_target_same_as_source = ::std::is_same< |
| typename ::std::remove_const< |
| typename ::std::remove_reference< |
| typename ::boost::mp11::mp_if< |
| ::boost::parameter::aux::has_nested_template_fn<Target> |
| , ::boost::parameter::aux |
| ::apply_target_fn<Target,Source,Args> |
| , ::boost::mpl::apply2< |
| ::boost::parameter::aux::as_placeholder_expr<Target> |
| , Source |
| , Args |
| > |
| >::type |
| >::type |
| >::type |
| , typename ::std::remove_const<Source>::type |
| >; |
| #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
| struct is_target_same_as_source |
| : ::boost::mpl::if_< |
| ::boost::is_same< |
| typename ::boost::remove_const< |
| typename ::boost::remove_reference< |
| typename ::boost::mpl::apply2< |
| ::boost::parameter::aux |
| ::as_placeholder_expr<Target> |
| , Source |
| , Args |
| >::type |
| >::type |
| >::type |
| , typename ::boost::remove_const<Source>::type |
| > |
| , ::boost::mpl::true_ |
| , ::boost::mpl::false_ |
| >::type |
| { |
| }; |
| #endif // BOOST_PARAMETER_CAN_USE_MP11 |
| }}} // namespace boost::parameter::aux |
| |
| #if !defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #include <boost/type_traits/add_const.hpp> |
| #include <boost/type_traits/is_const.hpp> |
| #endif |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| // Covers the case where is_convertible<Source,Target> but not |
| // is_same<Source,Target>. Use cases are covered |
| // by test/normalize_argument_types.cpp |
| template <typename Source, typename Target> |
| class cast_convert |
| { |
| typedef ::boost::parameter::aux::cast_convert<Source,Target> _self; |
| |
| public: |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| using type = typename ::boost::mp11::mp_if< |
| ::std::is_const<Source> |
| , ::std::add_const<Target> |
| , ::std::remove_const<Target> |
| >::type; |
| #else |
| typedef typename boost::mpl::eval_if< |
| ::boost::is_const<Source> |
| , ::boost::add_const<Target> |
| , ::boost::remove_const<Target> |
| >::type type; |
| #endif |
| |
| private: |
| inline static typename _self::type |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| _copy(typename ::std::remove_const<Target>::type value) |
| #else |
| _copy(typename ::boost::remove_const<Target>::type value) |
| #endif |
| { |
| return value; |
| } |
| |
| public: |
| inline static typename _self::type evaluate(Source&& source) |
| { |
| return _self::_copy(source); |
| } |
| }; |
| |
| template <typename Target, typename Source, typename Args> |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| using cast_impl = ::std::remove_reference< |
| typename ::boost::mp11::mp_if< |
| ::boost::parameter::aux::has_nested_template_fn<Target> |
| , ::boost::parameter::aux |
| ::is_target_same_as_source<Target,Source,Args> |
| , ::boost::mpl::apply2< |
| ::boost::parameter::aux::as_placeholder_expr<Target> |
| , Source |
| , Args |
| > |
| >::type |
| >; |
| #else |
| struct cast_impl |
| : ::boost::remove_reference< |
| typename ::boost::mpl::apply2< |
| ::boost::parameter::aux::as_placeholder_expr<Target> |
| , Source |
| , Args |
| >::type |
| > |
| { |
| }; |
| #endif // BOOST_PARAMETER_CAN_USE_MP11 |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/mpl/eval_if.hpp> |
| #include <boost/mpl/identity.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Target, typename Args> |
| struct cast<void(Target),Args> |
| { |
| template <typename T, typename B> |
| struct apply |
| { |
| typedef typename ::boost::mpl::eval_if< |
| B |
| , ::boost::mpl::eval_if< |
| ::boost::parameter::aux |
| ::is_target_same_as_source<Target,T,Args> |
| , ::boost::mpl::identity<T> |
| , ::boost::parameter::aux::cast_impl<Target,T,Args> |
| > |
| , ::boost::parameter::aux |
| ::is_target_same_as_source<Target,T,Args> |
| >::type type; |
| }; |
| |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| template <typename T, typename B> |
| using fn = typename ::boost::mp11::mp_if< |
| B |
| , ::boost::mp11::mp_if< |
| ::boost::parameter::aux |
| ::is_target_same_as_source<Target,T,Args> |
| , ::boost::mp11::mp_identity<T> |
| , ::boost::parameter::aux::cast_impl<Target,T,Args> |
| > |
| , ::boost::parameter::aux |
| ::is_target_same_as_source<Target,T,Args> |
| >::type; |
| #endif |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/parameter/value_type.hpp> |
| |
| #if !defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #include <boost/mpl/apply_wrap.hpp> |
| #endif |
| |
| // Expands to the target type of the argument as indicated by the predicate. |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #define BOOST_PARAMETER_FUNCTION_CAST_T(tag, predicate, args) \ |
| ::boost::mp11::mp_apply_q< \ |
| ::boost::parameter::aux::cast<void predicate, args> \ |
| , ::boost::mp11::mp_list< \ |
| typename ::boost::parameter::value_type< \ |
| args \ |
| , tag \ |
| , ::boost::parameter::aux::use_default_tag \ |
| >::type \ |
| , ::boost::mp11::mp_true \ |
| > \ |
| > |
| /**/ |
| #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #define BOOST_PARAMETER_FUNCTION_CAST_T(tag, predicate, args) \ |
| typename ::boost::mpl::apply_wrap2< \ |
| ::boost::parameter::aux::cast<void predicate, args> \ |
| , typename ::boost::parameter::value_type< \ |
| args \ |
| , tag \ |
| , ::boost::parameter::aux::use_default_tag \ |
| >::type \ |
| , ::boost::mpl::true_ \ |
| >::type |
| /**/ |
| #endif // BOOST_PARAMETER_CAN_USE_MP11 |
| |
| // Expands to boost::mpl::true_ if and only if the argument's source and |
| // target types are the same. |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #define BOOST_PARAMETER_FUNCTION_CAST_B(tag, predicate, args) \ |
| ::boost::mp11::mp_apply_q< \ |
| ::boost::parameter::aux::cast<void predicate, args> \ |
| , ::boost::mp11::mp_list< \ |
| typename ::boost::parameter::value_type< \ |
| args \ |
| , tag \ |
| , ::boost::parameter::aux::use_default_tag \ |
| >::type \ |
| , ::boost::mp11::mp_false \ |
| > \ |
| > |
| /**/ |
| #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) |
| #define BOOST_PARAMETER_FUNCTION_CAST_B(tag, predicate, args) \ |
| typename ::boost::mpl::apply_wrap2< \ |
| ::boost::parameter::aux::cast<void predicate, args> \ |
| , typename ::boost::parameter::value_type< \ |
| args \ |
| , tag \ |
| , ::boost::parameter::aux::use_default_tag \ |
| >::type \ |
| , ::boost::mpl::false_ \ |
| >::type |
| /**/ |
| #endif // BOOST_PARAMETER_CAN_USE_MP11 |
| |
| #include <boost/core/enable_if.hpp> |
| #include <utility> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| // If the source and target types are not the same, |
| // then perform an implicit conversion. |
| template <typename Target, typename B, typename Source> |
| inline typename ::boost::lazy_disable_if< |
| B |
| , ::boost::parameter::aux::cast_convert<Source,Target> |
| >::type |
| forward(Source&& source) |
| { |
| return ::boost::parameter::aux::cast_convert<Source,Target> |
| ::evaluate(::std::forward<Source>(source)); |
| } |
| |
| // If the source and target types are the same, |
| // then simply forward the argument. |
| // However, treat rvalue references to scalars as const lvalue references. |
| template <typename T, typename B> |
| inline typename ::boost::enable_if<B,T const&>::type forward(T const& t) |
| { |
| return t; |
| } |
| |
| template <typename T, typename B> |
| inline typename ::boost::enable_if< |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| ::boost::mp11::mp_if< |
| B |
| , ::boost::mp11::mp_if< |
| ::std::is_const<T> |
| , ::boost::mp11::mp_false |
| , ::boost::mp11::mp_true |
| > |
| , ::boost::mp11::mp_false |
| > |
| #else |
| typename ::boost::mpl::eval_if< |
| B |
| , ::boost::mpl::if_< |
| ::boost::is_const<T> |
| , ::boost::mpl::false_ |
| , ::boost::mpl::true_ |
| > |
| , ::boost::mpl::false_ |
| >::type |
| #endif // BOOST_PARAMETER_CAN_USE_MP11 |
| , T& |
| >::type |
| forward(T& t) |
| { |
| return t; |
| } |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/type_traits/is_scalar.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename T, typename B> |
| inline typename ::boost::enable_if< |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| ::boost::mp11::mp_if< |
| B |
| , ::boost::mp11::mp_if< |
| ::std::is_scalar<T> |
| , ::boost::mp11::mp_false |
| , ::boost::mp11::mp_true |
| > |
| , ::boost::mp11::mp_false |
| > |
| #else |
| typename ::boost::mpl::eval_if< |
| B |
| , ::boost::mpl::if_< |
| ::boost::is_scalar<T> |
| , ::boost::mpl::false_ |
| , ::boost::mpl::true_ |
| > |
| , ::boost::mpl::false_ |
| >::type |
| #endif // BOOST_PARAMETER_CAN_USE_MP11 |
| , T const&& |
| >::type |
| forward(T const&& t) |
| { |
| return static_cast<T const&&>(t); |
| } |
| |
| template <typename T, typename B> |
| inline typename ::boost::enable_if< |
| #if defined(BOOST_PARAMETER_CAN_USE_MP11) |
| ::boost::mp11::mp_if< |
| B |
| , ::boost::mp11::mp_if< |
| ::std::is_scalar<T> |
| , ::boost::mp11::mp_false |
| , ::boost::mp11::mp_true |
| > |
| , ::boost::mp11::mp_false |
| > |
| #else |
| typename ::boost::mpl::eval_if< |
| B |
| , ::boost::mpl::if_< |
| ::boost::is_scalar<T> |
| , ::boost::mpl::false_ |
| , ::boost::mpl::true_ |
| > |
| , ::boost::mpl::false_ |
| >::type |
| #endif // BOOST_PARAMETER_CAN_USE_MP11 |
| , T&& |
| >::type |
| forward(T&& t) |
| { |
| return ::std::forward<T>(t); |
| } |
| }}} // namespace boost::parameter::aux |
| |
| #elif BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) |
| #define BOOST_PARAMETER_FUNCTION_CAST_T(value_t, predicate, args) value_t |
| #define BOOST_PARAMETER_FUNCTION_CAST_B(value, predicate, args) value |
| #else // no perfect forwarding support and no Borland workarounds needed |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| // Handles possible implicit casts. Used by preprocessor.hpp |
| // to normalize user input. |
| // |
| // cast<void*>::execute() is identity |
| // cast<void*(X)>::execute() is identity |
| // cast<void(X)>::execute() casts to X |
| // |
| // preprocessor.hpp uses this like this: |
| // |
| // #define X(value, predicate) |
| // cast<void predicate>::execute(value) |
| // |
| // X(something, *) |
| // X(something, *(predicate)) |
| // X(something, (int)) |
| template <typename VoidExpr, typename Args> |
| struct cast; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/parameter/aux_/use_default_tag.hpp> |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/if.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Args> |
| struct cast<void*,Args> |
| { |
| template <typename T> |
| struct apply |
| { |
| typedef T& type; |
| }; |
| |
| inline static ::boost::parameter::aux::use_default_tag |
| execute(::boost::parameter::aux::use_default_tag) |
| { |
| return ::boost::parameter::aux::use_default_tag(); |
| } |
| |
| template <typename U> |
| inline static U& execute(U& value) |
| { |
| return value; |
| } |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/parameter/aux_/void.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Predicate, typename Args> |
| #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580)) |
| struct cast< ::boost::parameter::aux::voidstar(Predicate),Args> |
| #else |
| struct cast<void*(Predicate),Args> |
| #endif |
| : ::boost::parameter::aux::cast<void*,Args> |
| { |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/mpl/placeholders.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| // This is a hack used in cast<> to turn the user supplied type, |
| // which may or may not be a placeholder expression, into one, |
| // so that it will be properly evaluated by mpl::apply. |
| template <typename T, typename Dummy = ::boost::mpl::_1> |
| struct as_placeholder_expr |
| { |
| typedef T type; |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/mpl/apply.hpp> |
| #include <boost/type_traits/is_same.hpp> |
| #include <boost/type_traits/remove_const.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Target, typename Source, typename Args> |
| struct is_target_same_as_source |
| : ::boost::mpl::if_< |
| ::boost::is_same< |
| typename ::boost::remove_const< |
| typename ::boost::remove_reference< |
| typename ::boost::mpl::apply2< |
| ::boost::parameter::aux |
| ::as_placeholder_expr<Target> |
| , Source |
| , Args |
| >::type |
| >::type |
| >::type |
| , typename ::boost::remove_const<Source>::type |
| > |
| , ::boost::mpl::true_ |
| , ::boost::mpl::false_ |
| >::type |
| { |
| }; |
| |
| template < |
| typename Target |
| , typename Source |
| , typename Args |
| , typename Enable = ::boost::parameter::aux |
| ::is_target_same_as_source<Target,Source,Args> |
| > |
| struct cast_impl |
| { |
| typedef Source& type; |
| |
| inline static Source& evaluate(Source& value) |
| { |
| return value; |
| } |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/type_traits/add_const.hpp> |
| #include <boost/type_traits/add_lvalue_reference.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| // Covers the case where is_convertible<Source,Target> but not |
| // is_same<Source,Target>. Use cases are covered |
| // by test/normalize_argument_types.cpp |
| template <typename Source, typename Target> |
| class cast_convert |
| { |
| typedef ::boost::parameter::aux::cast_convert<Source,Target> _self; |
| |
| public: |
| typedef typename ::boost::add_lvalue_reference< |
| typename ::boost::add_const<Target>::type |
| >::type type; |
| |
| private: |
| template <typename U> |
| inline static typename _self::type _mod_const(U const& u) |
| { |
| return u; |
| } |
| |
| inline static Target _copy(Target value) |
| { |
| return value; |
| } |
| |
| public: |
| inline static typename _self::type evaluate(Source& source) |
| { |
| return _self::_mod_const(_self::_copy(source)); |
| } |
| }; |
| |
| template <typename Target, typename Source, typename Args> |
| struct cast_impl<Target,Source,Args,::boost::mpl::false_> |
| : ::boost::parameter::aux::cast_convert< |
| Source, |
| typename ::boost::mpl::apply2< |
| ::boost::parameter::aux::as_placeholder_expr<Target> |
| , Source |
| , Args |
| >::type |
| > |
| { |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/mpl/eval_if.hpp> |
| |
| namespace boost { namespace parameter { namespace aux { |
| |
| template <typename Target, typename Args> |
| struct cast<void(Target),Args> |
| { |
| template <typename T> |
| struct apply |
| { |
| typedef typename ::boost::mpl::eval_if< |
| ::boost::parameter::aux |
| ::is_target_same_as_source<Target,T,Args> |
| , ::boost::add_lvalue_reference<T> |
| , ::boost::parameter::aux::cast_impl< |
| Target |
| , T |
| , Args |
| , ::boost::mpl::false_ |
| > |
| >::type type; |
| }; |
| |
| inline static ::boost::parameter::aux::use_default_tag |
| execute(::boost::parameter::aux::use_default_tag) |
| { |
| return ::boost::parameter::aux::use_default_tag(); |
| } |
| |
| template <typename U> |
| inline static typename ::boost::parameter::aux |
| ::cast_impl<Target,U const,Args>::type |
| execute(U const& value) |
| { |
| return ::boost::parameter::aux |
| ::cast_impl<Target,U const,Args>::evaluate(value); |
| } |
| |
| template <typename U> |
| inline static typename ::boost::parameter::aux |
| ::cast_impl<Target,U,Args>::type |
| execute(U& value) |
| { |
| return ::boost::parameter::aux |
| ::cast_impl<Target,U,Args>::evaluate(value); |
| } |
| }; |
| }}} // namespace boost::parameter::aux |
| |
| #include <boost/mpl/apply_wrap.hpp> |
| #include <boost/parameter/value_type.hpp> |
| |
| // Expands to the reference-qualified target type of the argument |
| // as indicated by the predicate. |
| #define BOOST_PARAMETER_FUNCTION_CAST_T(tag, predicate, args) \ |
| typename ::boost::mpl::apply_wrap1< \ |
| ::boost::parameter::aux::cast<void predicate, args> \ |
| , typename ::boost::parameter::value_type< \ |
| args \ |
| , tag \ |
| , ::boost::parameter::aux::use_default_tag \ |
| >::type \ |
| >::type |
| /**/ |
| |
| // Expands to the converted or passed-through value |
| // as indicated by the predicate. |
| #define BOOST_PARAMETER_FUNCTION_CAST_B(value, predicate, args) \ |
| ::boost::parameter::aux::cast<void predicate, args>::execute(value) |
| /**/ |
| |
| #endif // perfect forwarding support, or Borland workarounds needed |
| #endif // include guard |
| |