summaryrefslogtreecommitdiff
path: root/boost/parameter/aux_/preprocessor/impl/function_cast.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/parameter/aux_/preprocessor/impl/function_cast.hpp')
-rw-r--r--boost/parameter/aux_/preprocessor/impl/function_cast.hpp730
1 files changed, 730 insertions, 0 deletions
diff --git a/boost/parameter/aux_/preprocessor/impl/function_cast.hpp b/boost/parameter/aux_/preprocessor/impl/function_cast.hpp
new file mode 100644
index 0000000000..2c40a25798
--- /dev/null
+++ b/boost/parameter/aux_/preprocessor/impl/function_cast.hpp
@@ -0,0 +1,730 @@
+// 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(__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
+