// 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
|