1 // Copyright Daniel Wallin, David Abrahams 2005. 2 // Copyright Cromwell D. Enage 2017. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef BOOST_PARAMETER_AUX_UNWRAP_CV_REFERENCE_HPP 8 #define BOOST_PARAMETER_AUX_UNWRAP_CV_REFERENCE_HPP 9 10 namespace boost { 11 12 template <typename T> 13 class reference_wrapper; 14 } // namespace boost 15 16 #include <boost/parameter/aux_/yesno.hpp> 17 18 namespace boost { namespace parameter { namespace aux { 19 20 // 21 // reference_wrapper support -- if perfect forwarding is unsupported, 22 // then when passing arguments positionally by non-const reference, 23 // we ask users of named parameter interfaces to use ref(x) to wrap them. 24 // 25 26 template <typename U> 27 ::boost::parameter::aux::yes_tag 28 is_cv_reference_wrapper_check( 29 ::boost::reference_wrapper<U> const volatile* 30 ); 31 32 ::boost::parameter::aux::no_tag is_cv_reference_wrapper_check(...); 33 }}} // namespace boost::parameter::aux 34 35 #include <boost/parameter/config.hpp> 36 37 #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) 38 #include <functional> 39 40 namespace boost { namespace parameter { namespace aux { 41 42 // Support for std::ref(x) -- Cromwell D. Enage 43 template <typename U> 44 ::boost::parameter::aux::yes_tag 45 is_cv_reference_wrapper_check( 46 ::std::reference_wrapper<U> const volatile* 47 ); 48 }}} // namespace boost::parameter::aux 49 #endif 50 51 #include <boost/parameter/aux_/preprocessor/nullptr.hpp> 52 53 #if defined(BOOST_PARAMETER_CAN_USE_MP11) && !( \ 54 BOOST_WORKAROUND(BOOST_MSVC, >= 1900) && \ 55 BOOST_WORKAROUND(BOOST_MSVC, < 1910) \ 56 ) 57 #include <boost/mp11/integral.hpp> 58 #include <boost/mp11/utility.hpp> 59 #include <type_traits> 60 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) || MSVC-14.0 61 #include <boost/mpl/bool.hpp> 62 #include <boost/type_traits/remove_reference.hpp> 63 #if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) && \ 64 !BOOST_WORKAROUND(BOOST_GCC, < 40000) 65 #include <boost/mpl/eval_if.hpp> 66 #endif 67 #endif // BOOST_PARAMETER_CAN_USE_MP11 && not MSVC-14.0 68 69 namespace boost { namespace parameter { namespace aux { 70 71 #if defined(BOOST_PARAMETER_CAN_USE_MP11) && !( \ 72 BOOST_WORKAROUND(BOOST_MSVC, >= 1900) && \ 73 BOOST_WORKAROUND(BOOST_MSVC, < 1910) \ 74 ) 75 // This metafunction returns mp11::mp_true if T is of type 76 // reference_wrapper<U> cv. 77 template <typename T> 78 using is_cv_reference_wrapper = ::boost::mp11::mp_bool< 79 sizeof( 80 ::boost::parameter::aux::is_cv_reference_wrapper_check( 81 static_cast< 82 typename ::std::remove_reference<T>::type* 83 >(BOOST_PARAMETER_AUX_PP_NULLPTR) 84 ) 85 ) == sizeof(::boost::parameter::aux::yes_tag) 86 >; 87 88 // Needed for unwrap_cv_reference below. T might be const, so 89 // mp_eval_if<> might fail because of deriving from T const on EDG. 90 template <typename T> 91 using unwrap_cv_reference_impl = typename ::std::remove_reference<T>::type; 92 93 // Produces the unwrapped type to hold a reference to in 94 // tagged_argument<>. Can't use boost::unwrap_reference<> here 95 // because it doesn't handle the case where T = reference_wrapper<U> cv. 96 template <typename T> 97 using unwrap_cv_reference = ::boost::mp11::mp_eval_if< 98 ::boost::parameter::aux::is_cv_reference_wrapper<T> 99 , ::boost::parameter::aux::unwrap_cv_reference_impl<T> 100 , ::std::remove_reference 101 , T 102 >; 103 #else // !defined(BOOST_PARAMETER_CAN_USE_MP11) || MSVC-14.0 104 // This metafunction returns mpl::true_ if T is of type 105 // reference_wrapper<U> cv. 106 template <typename T> 107 struct is_cv_reference_wrapper 108 { 109 BOOST_STATIC_CONSTANT( 110 bool, value = ( 111 sizeof( 112 ::boost::parameter::aux::is_cv_reference_wrapper_check( 113 static_cast< 114 typename ::boost::remove_reference<T>::type* 115 >(BOOST_PARAMETER_AUX_PP_NULLPTR) 116 ) 117 ) == sizeof(::boost::parameter::aux::yes_tag) 118 ) 119 ); 120 121 typedef boost::mpl::bool_< 122 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) 123 is_cv_reference_wrapper:: 124 #endif 125 value> type; 126 }; 127 128 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) || \ 129 BOOST_WORKAROUND(BOOST_GCC, < 40000) 130 template < 131 typename T 132 , typename = typename ::boost::parameter::aux 133 ::is_cv_reference_wrapper<T>::type 134 > 135 struct unwrap_cv_reference : ::boost::remove_reference<T> 136 { 137 }; 138 139 template <typename T> 140 struct unwrap_cv_reference<T const,::boost::mpl::false_> 141 { 142 typedef T const type; 143 }; 144 145 template <typename T> 146 struct unwrap_cv_reference<T,::boost::mpl::true_> : T 147 { 148 }; 149 #else // no Borland or GCC 3- workarounds needed 150 // Needed for unwrap_cv_reference below. T might be const, so 151 // eval_if<> might fail because of deriving from T const on EDG. 152 template <typename T> 153 struct unwrap_cv_reference_impl : ::boost::remove_reference<T>::type 154 { 155 }; 156 157 // Produces the unwrapped type to hold a reference to in 158 // tagged_argument<>. Can't use boost::unwrap_reference<> here 159 // because it doesn't handle the case where T = reference_wrapper<U> cv. 160 template <typename T> 161 struct unwrap_cv_reference 162 : ::boost::mpl::eval_if< 163 ::boost::parameter::aux::is_cv_reference_wrapper<T> 164 , ::boost::parameter::aux::unwrap_cv_reference_impl<T> 165 , ::boost::remove_reference<T> 166 > 167 { 168 }; 169 #endif // Borland or GCC 3- workarounds needed 170 #endif // BOOST_PARAMETER_CAN_USE_MP11 && not MSVC-14.0 171 }}} // namespace boost::parameter::aux 172 173 #endif // include guard 174 175