// 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 #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::execute() is identity // cast::execute() is identity // cast::execute() casts to X // // preprocessor.hpp uses this like this: // // #define X(value, predicate) // cast::execute(value) // // X(something, *) // X(something, *(predicate)) // X(something, (int)) template struct cast; }}} // namespace boost::parameter::aux #include namespace boost { namespace parameter { namespace aux { template 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 #include #if defined(BOOST_PARAMETER_CAN_USE_MP11) #include #include #endif namespace boost { namespace parameter { namespace aux { template struct cast { template struct apply { typedef typename ::boost::mpl ::if_::type type; }; #if defined(BOOST_PARAMETER_CAN_USE_MP11) template using fn = ::boost::mp11::mp_if; #endif }; }}} // namespace boost::parameter::aux #include namespace boost { namespace parameter { namespace aux { template struct cast : ::boost::parameter::aux::cast { }; }}} // namespace boost::parameter::aux #include 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 struct as_placeholder_expr { typedef T type; }; }}} // namespace boost::parameter::aux #if defined(BOOST_PARAMETER_CAN_USE_MP11) #include namespace boost { namespace parameter { namespace aux { template struct apply_target_fn { using type = ::boost::mp11 ::mp_apply_q >; }; }}} // namespace boost::parameter::aux #endif #include #if defined(BOOST_PARAMETER_CAN_USE_MP11) #include #include #else #include #include #include #endif namespace boost { namespace parameter { namespace aux { template #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 , ::boost::parameter::aux ::apply_target_fn , ::boost::mpl::apply2< ::boost::parameter::aux::as_placeholder_expr , Source , Args > >::type >::type >::type , typename ::std::remove_const::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 , Source , Args >::type >::type >::type , typename ::boost::remove_const::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 #include #endif namespace boost { namespace parameter { namespace aux { // Covers the case where is_convertible but not // is_same. Use cases are covered // by test/normalize_argument_types.cpp template class cast_convert { typedef ::boost::parameter::aux::cast_convert _self; public: #if defined(BOOST_PARAMETER_CAN_USE_MP11) using type = typename ::boost::mp11::mp_if< ::std::is_const , ::std::add_const , ::std::remove_const >::type; #else typedef typename boost::mpl::eval_if< ::boost::is_const , ::boost::add_const , ::boost::remove_const >::type type; #endif private: inline static typename _self::type #if defined(BOOST_PARAMETER_CAN_USE_MP11) _copy(typename ::std::remove_const::type value) #else _copy(typename ::boost::remove_const::type value) #endif { return value; } public: inline static typename _self::type evaluate(Source&& source) { return _self::_copy(source); } }; template #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 , ::boost::parameter::aux ::is_target_same_as_source , ::boost::mpl::apply2< ::boost::parameter::aux::as_placeholder_expr , Source , Args > >::type >; #else struct cast_impl : ::boost::remove_reference< typename ::boost::mpl::apply2< ::boost::parameter::aux::as_placeholder_expr , Source , Args >::type > { }; #endif // BOOST_PARAMETER_CAN_USE_MP11 }}} // namespace boost::parameter::aux #include #include namespace boost { namespace parameter { namespace aux { template struct cast { template struct apply { typedef typename ::boost::mpl::eval_if< B , ::boost::mpl::eval_if< ::boost::parameter::aux ::is_target_same_as_source , ::boost::mpl::identity , ::boost::parameter::aux::cast_impl > , ::boost::parameter::aux ::is_target_same_as_source >::type type; }; #if defined(BOOST_PARAMETER_CAN_USE_MP11) template using fn = typename ::boost::mp11::mp_if< B , ::boost::mp11::mp_if< ::boost::parameter::aux ::is_target_same_as_source , ::boost::mp11::mp_identity , ::boost::parameter::aux::cast_impl > , ::boost::parameter::aux ::is_target_same_as_source >::type; #endif }; }}} // namespace boost::parameter::aux #include #if !defined(BOOST_PARAMETER_CAN_USE_MP11) #include #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 \ , ::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 \ , 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 \ , ::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 \ , 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 #include namespace boost { namespace parameter { namespace aux { // If the source and target types are not the same, // then perform an implicit conversion. template inline typename ::boost::lazy_disable_if< B , ::boost::parameter::aux::cast_convert >::type forward(Source&& source) { return ::boost::parameter::aux::cast_convert ::evaluate(::std::forward(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 inline typename ::boost::enable_if::type forward(T const& t) { return t; } template inline typename ::boost::enable_if< #if defined(BOOST_PARAMETER_CAN_USE_MP11) ::boost::mp11::mp_if< B , ::boost::mp11::mp_if< ::std::is_const , ::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 , ::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 namespace boost { namespace parameter { namespace aux { template inline typename ::boost::enable_if< #if defined(BOOST_PARAMETER_CAN_USE_MP11) ::boost::mp11::mp_if< B , ::boost::mp11::mp_if< ::std::is_scalar , ::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 , ::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); } template inline typename ::boost::enable_if< #if defined(BOOST_PARAMETER_CAN_USE_MP11) ::boost::mp11::mp_if< B , ::boost::mp11::mp_if< ::std::is_scalar , ::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 , ::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); } }}} // 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::execute() is identity // cast::execute() is identity // cast::execute() casts to X // // preprocessor.hpp uses this like this: // // #define X(value, predicate) // cast::execute(value) // // X(something, *) // X(something, *(predicate)) // X(something, (int)) template struct cast; }}} // namespace boost::parameter::aux #include #include #include namespace boost { namespace parameter { namespace aux { template struct cast { template 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 inline static U& execute(U& value) { return value; } }; }}} // namespace boost::parameter::aux #include namespace boost { namespace parameter { namespace aux { template #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580)) struct cast< ::boost::parameter::aux::voidstar(Predicate),Args> #else struct cast #endif : ::boost::parameter::aux::cast { }; }}} // namespace boost::parameter::aux #include 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 struct as_placeholder_expr { typedef T type; }; }}} // namespace boost::parameter::aux #include #include #include #include namespace boost { namespace parameter { namespace aux { template 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 , Source , Args >::type >::type >::type , typename ::boost::remove_const::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 > struct cast_impl { typedef Source& type; inline static Source& evaluate(Source& value) { return value; } }; }}} // namespace boost::parameter::aux #include #include namespace boost { namespace parameter { namespace aux { // Covers the case where is_convertible but not // is_same. Use cases are covered // by test/normalize_argument_types.cpp template class cast_convert { typedef ::boost::parameter::aux::cast_convert _self; public: typedef typename ::boost::add_lvalue_reference< typename ::boost::add_const::type >::type type; private: template 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 struct cast_impl : ::boost::parameter::aux::cast_convert< Source, typename ::boost::mpl::apply2< ::boost::parameter::aux::as_placeholder_expr , Source , Args >::type > { }; }}} // namespace boost::parameter::aux #include namespace boost { namespace parameter { namespace aux { template struct cast { template struct apply { typedef typename ::boost::mpl::eval_if< ::boost::parameter::aux ::is_target_same_as_source , ::boost::add_lvalue_reference , ::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 inline static typename ::boost::parameter::aux ::cast_impl::type execute(U const& value) { return ::boost::parameter::aux ::cast_impl::evaluate(value); } template inline static typename ::boost::parameter::aux ::cast_impl::type execute(U& value) { return ::boost::parameter::aux ::cast_impl::evaluate(value); } }; }}} // namespace boost::parameter::aux #include #include // 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 \ , 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::execute(value) /**/ #endif // perfect forwarding support, or Borland workarounds needed #endif // include guard