📄 traits.hpp
字号:
#ifndef BOOST_PP_IS_ITERATING /////////////////////////////////////////////////////////////////////////////// /// \file traits.hpp /// Contains definitions for arg\<\>, arg_c\<\>, left\<\>, /// right\<\>, tag_of\<\>, and the helper functions arg(), arg_c(), /// left() and right(). // // Copyright 2008 Eric Niebler. 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_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 #include <boost/xpressive/proto/detail/prefix.hpp> #include <boost/config.hpp> #include <boost/detail/workaround.hpp> #include <boost/preprocessor/iteration/iterate.hpp> #include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_trailing.hpp> #include <boost/preprocessor/repetition/enum_trailing_params.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/repetition/repeat_from_to.hpp> #include <boost/preprocessor/facilities/intercept.hpp> #include <boost/preprocessor/arithmetic/sub.hpp> #include <boost/ref.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/or.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/aux_/template_arity.hpp> #include <boost/mpl/aux_/lambda_arity_param.hpp> #include <boost/static_assert.hpp> #include <boost/utility/result_of.hpp> #include <boost/type_traits/is_pod.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_array.hpp> #include <boost/type_traits/is_function.hpp> #include <boost/type_traits/remove_cv.hpp> #include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/add_reference.hpp> #include <boost/xpressive/proto/proto_fwd.hpp> #include <boost/xpressive/proto/ref.hpp> #include <boost/xpressive/proto/args.hpp> #include <boost/xpressive/proto/tags.hpp> #include <boost/xpressive/proto/transform/pass_through.hpp> #include <boost/xpressive/proto/detail/suffix.hpp> #if BOOST_WORKAROUND( BOOST_MSVC, == 1310 ) #define BOOST_PROTO_IS_ARRAY_(T) boost::is_array<typename boost::remove_const<T>::type> #else #define BOOST_PROTO_IS_ARRAY_(T) boost::is_array<T> #endif #if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 ) #pragma warning(push) #pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored #endif namespace boost { namespace proto { namespace detail { template<typename T, typename Void = void> struct if_vararg {}; template<typename T> struct if_vararg<T, typename T::proto_is_vararg_> : T {}; template<typename T, typename Void = void> struct is_callable2_ : mpl::false_ {}; template<typename T> struct is_callable2_<T, typename T::proto_is_callable_> : mpl::true_ {}; template<typename T BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(long Arity = mpl::aux::template_arity<T>::value)> struct is_callable_ : is_callable2_<T> {}; } /// \brief Boolean metafunction which detects whether a type is /// a callable function object type or not. /// /// <tt>is_callable\<\></tt> is used by the <tt>when\<\></tt> transform /// to determine whether a function type <tt>R(A1,A2,...AN)</tt> is a /// callable transform or an object transform. (The former are evaluated /// using <tt>call\<\></tt> and the later with <tt>make\<\></tt>.) If /// <tt>is_callable\<R\>::::value</tt> is \c true, the function type is /// a callable transform; otherwise, it is an object transform. /// /// Unless specialized for a type \c T, <tt>is_callable\<T\>::::value</tt> /// is computed as follows: /// /// \li If \c T is a template type <tt>X\<Y0,Y1,...YN\></tt>, where all \c Yx /// are types for \c x in <tt>[0,N]</tt>, <tt>is_callable\<T\>::::value</tt> /// is <tt>is_same\<YN, proto::callable\>::::value</tt>. /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef /// for \c void, <tt>is_callable\<T\>::::value</tt> is \c true. (Note: this is /// the case for any type that derives from \c proto::callable.) /// \li Otherwise, <tt>is_callable\<T\>::::value</tt> is \c false. template<typename T> struct is_callable : proto::detail::is_callable_<T> {}; /// INTERNAL ONLY /// template<> struct is_callable<proto::_> : mpl::true_ {}; /// INTERNAL ONLY /// template<> struct is_callable<proto::callable> : mpl::false_ {}; #if BOOST_WORKAROUND(__GNUC__, == 3) // work around GCC bug template<typename Tag, typename Args, long N> struct is_callable<proto::expr<Tag, Args, N> > : mpl::false_ {}; #endif /// \brief A Boolean metafunction that indicates whether a type requires /// aggregate initialization. /// /// <tt>is_aggregate\<\></tt> is used by the <tt>make\<\></tt> transform /// to determine how to construct an object of some type \c T, given some /// initialization arguments <tt>a0,a1,...aN</tt>. /// If <tt>is_aggregate\<T\>::::value</tt> is \c true, then an object of /// type T will be initialized as <tt>T t = {a0,a1,...aN};</tt>. Otherwise, /// it will be initialized as <tt>T t(a0,a1,...aN)</tt>. template<typename T> struct is_aggregate : is_pod<T> {}; /// \brief Specialization of <tt>is_aggregate\<\></tt> that indicates /// that objects of <tt>expr\<\></tt> type require aggregate initialization. template<typename Tag, typename Args, long N> struct is_aggregate<proto::expr<Tag, Args, N> > : mpl::true_ {}; namespace result_of { /// \brief A Boolean metafunction that indicates whether a given /// type \c T is a Proto expression type. /// /// If \c T has a nested type \c proto_is_expr_ that is a typedef /// for \c void, <tt>is_expr\<T\>::::value</tt> is \c true. (Note, this /// is the case for <tt>proto::expr\<\></tt>, any type that is derived /// from <tt>proto::extends\<\></tt> or that uses the /// <tt>BOOST_PROTO_EXTENDS()</tt> macro.) Otherwise, /// <tt>is_expr\<T\>::::value</tt> is \c false. template<typename T, typename Void BOOST_PROTO_FOR_DOXYGEN_ONLY(= void)> struct is_expr : mpl::false_ {}; /// \brief A Boolean metafunction that indicates whether a given /// type \c T is a Proto expression type. /// /// If \c T has a nested type \c proto_is_expr_ that is a typedef /// for \c void, <tt>is_expr\<T\>::::value</tt> is \c true. (Note, this /// is the case for <tt>proto::expr\<\></tt>, any type that is derived /// from <tt>proto::extends\<\></tt> or that uses the /// <tt>BOOST_PROTO_EXTENDS()</tt> macro.) Otherwise, /// <tt>is_expr\<T\>::::value</tt> is \c false. template<typename T> struct is_expr<T, typename T::proto_is_expr_> : mpl::true_ {}; /// \brief A metafunction that returns the tag type of a /// Proto expression. template<typename Expr> struct tag_of { typedef typename Expr::proto_tag type; }; /// INTERNAL ONLY /// template<typename T, typename Void BOOST_PROTO_FOR_DOXYGEN_ONLY(= void)> struct is_ref : mpl::false_ {}; /// INTERNAL ONLY /// template<typename T> struct is_ref<T, typename T::proto_is_ref_> : mpl::true_ {}; /// \brief A metafunction that computes the return type of the \c as_expr() /// function. /// /// The <tt>as_expr\<\></tt> metafunction turns types into Proto types, if /// they are not already, by making them Proto terminals held by value if /// possible. Types which are already Proto types are left alone. /// /// This specialization is selected when the type is not yet a Proto type. /// The resulting terminal type is calculated as follows: /// /// If \c T is an array type or a function type, let \c A be <tt>T &</tt>. /// Otherwise, let \c A be the type \c T stripped of cv-qualifiers. /// Then, the result type <tt>as_expr\<T, Domain\>::::type</tt> is /// <tt>Domain::apply\< expr\< tag::terminal, args0\<A\> \> \>::::type</tt>. template< typename T , typename Domain BOOST_PROTO_FOR_DOXYGEN_ONLY(= default_domain) , typename Void BOOST_PROTO_FOR_DOXYGEN_ONLY(= void) > struct as_expr { typedef mpl::or_<BOOST_PROTO_IS_ARRAY_(T), is_function<T> > is_unstorable_; typedef typename mpl::eval_if<is_unstorable_, add_reference<T>, remove_cv<T> >::type arg0_; typedef proto::expr<proto::tag::terminal, args0<arg0_> > expr_; typedef typename Domain::template apply<expr_>::type type; typedef type const reference; /// INTERNAL ONLY /// template<typename T2> static reference call(T2 &t) { return Domain::make(expr_::make(t)); } }; /// \brief A metafunction that computes the return type of the \c as_expr() /// function. /// /// The <tt>as_expr\<\></tt> metafunction turns types into Proto types, if /// they are not already, by making them Proto terminals held by value if /// possible. Types which are already Proto types are left alone. /// /// This specialization is selected when the type is already a Proto type. /// The result type <tt>as_expr\<T, Domain\>::::type</tt> is \c T stripped /// of cv-qualifiers. template<typename T, typename Domain> struct as_expr<T, Domain, typename T::proto_is_expr_> { typedef typename T::proto_derived_expr type; typedef T &reference; /// INTERNAL ONLY /// template<typename T2> static reference call(T2 &t) { return t; } }; /// \brief A metafunction that computes the return type of the \c as_arg() /// function. /// /// The <tt>as_arg\<\></tt> metafunction turns types into Proto types, if /// they are not already, by making them Proto terminals held by reference. /// Types which are already Proto types are wrapped in <tt>proto::ref_\<\></tt>. /// /// This specialization is selected when the type is not yet a Proto type. /// The result type <tt>as_arg\<T, Domain\>::::type</tt> is /// <tt>Domain::apply\< expr\< tag::terminal, args0\<T &\> \> \>::::type</tt>. template< typename T , typename Domain BOOST_PROTO_FOR_DOXYGEN_ONLY(= default_domain) , typename Void BOOST_PROTO_FOR_DOXYGEN_ONLY(= void) > struct as_arg { typedef proto::expr<proto::tag::terminal, args0<T &> > expr_; typedef typename Domain::template apply<expr_>::type type; /// INTERNAL ONLY /// template<typename T2> static type call(T2 &t) { return Domain::make(expr_::make(t)); } }; /// \brief A metafunction that computes the return type of the \c as_arg() /// function. ///
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -