return_type_traits.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 285 行

HPP
285
字号
//  return_type_traits.hpp -- Boost Lambda Library ---------------------------// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)//// 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)//// For more information, see www.boost.org#ifndef BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP#define BOOST_LAMBDA_RETURN_TYPE_TRAITS_HPP#include "boost/mpl/has_xxx.hpp"#include <cstddef> // needed for the ptrdiff_tnamespace boost { namespace lambda {using ::boost::type_traits::ice_and;using ::boost::type_traits::ice_or;using ::boost::type_traits::ice_not;// Much of the type deduction code for standard arithmetic types // from Gary Powell  // different arities:template <class Act, class A1> struct return_type_1; // 1-ary actionstemplate <class Act, class A1, class A2> struct return_type_2; // 2-arytemplate <class Act, class Args> struct return_type_N; // >3- arytemplate <class Act, class A1> struct return_type_1_prot;template <class Act, class A1, class A2> struct return_type_2_prot; // 2-arytemplate <class Act, class A1> struct return_type_N_prot; // >3-arynamespace detail {template<class> class return_type_deduction_failure {};  // In some cases return type deduction should fail (an invalid lambda   // expression). Sometimes the lambda expression can be ok, the return type  // just is not deducible (user defined operators). Then return type deduction  // should never be entered at all, and the use of ret<> does this.  // However, for nullary lambda functors, return type deduction is always  // entered, and there seems to be no way around this.  // (the return type is part of the prototype of the non-template  // operator()(). The prototype is instantiated, even though the body   // is not.)    // So, in the case the return type deduction should fail, it should not  // fail directly, but rather result in a valid but wrong return type,  // causing a compile time error only if the function is really called.} // end detail// return_type_X_prot classes --------------------------------------------// These classes are the first layer that gets instantiated from the // lambda_functor_base sig templates. It will check whether // the action is protectable and one of arguments is "protected" or its// evaluation will otherwise result in another lambda functor.// If this is a case, the result type will be another lambda functor.// The arguments are always non-reference types, except for comma action// where the right argument can be a reference too. This is because it // matters (in the builtin case) whether the argument is an lvalue or // rvalue: int i; i, 1 -> rvalue; 1, i -> lvaluetemplate <class Act, class A> struct return_type_1_prot {public:  typedef typename     detail::IF<  //      is_protectable<Act>::value && is_lambda_functor<A>::value,      ice_and<is_protectable<Act>::value, is_lambda_functor<A>::value>::value,      lambda_functor<        lambda_functor_base<           Act,           tuple<typename detail::remove_reference_and_cv<A>::type>        >      >,      typename return_type_1<Act, A>::type    >::RET type;  };  // take care of the unavoidable instantiation for nullary casetemplate<class Act> struct return_type_1_prot<Act, null_type> {  typedef null_type type;}; // Unary actions (result from unary operators)// do not have a default return type.template<class Act, class A> struct return_type_1 {    typedef typename      detail::return_type_deduction_failure<return_type_1> type;};namespace detail {  template <class T>  class protect_conversion {      typedef typename boost::remove_reference<T>::type non_ref_T;    public:  // add const to rvalues, so that all rvalues are stored as const in   // the args tuple    typedef typename detail::IF_type<//      boost::is_reference<T>::value && !boost::is_const<non_ref_T>::value,      ice_and<boost::is_reference<T>::value,              ice_not<boost::is_const<non_ref_T>::value>::value>::value,      detail::identity_mapping<T>,      const_copy_argument<non_ref_T> // handles funtion and array     >::type type;                      // types correctly  };} // end detailtemplate <class Act, class A, class B> struct return_type_2_prot {// experimental feature  // We may have a lambda functor as a result type of a subexpression   // (if protect) has  been used.  // Thus, if one of the parameter types is a lambda functor, the result  // is a lambda functor as well.   // We need to make a conservative choise here.  // The resulting lambda functor stores all const reference arguments as  // const copies. References to non-const are stored as such.  // So if the source of the argument is a const open argument, a bound  // argument stored as a const reference, or a function returning a   // const reference, that information is lost. There is no way of   // telling apart 'real const references' from just 'LL internal  // const references' (or it would be really hard)  // The return type is a subclass of lambda_functor, which has a converting   // copy constructor. It can copy any lambda functor, that has the same   // action type and code, and a copy compatible argument tuple.  typedef typename boost::remove_reference<A>::type non_ref_A;  typedef typename boost::remove_reference<B>::type non_ref_B;typedef typename   detail::IF<//    is_protectable<Act>::value &&//      (is_lambda_functor<A>::value || is_lambda_functor<B>::value),    ice_and<is_protectable<Act>::value,            ice_or<is_lambda_functor<A>::value,                    is_lambda_functor<B>::value>::value>::value,    lambda_functor<      lambda_functor_base<         Act,         tuple<typename detail::protect_conversion<A>::type,               typename detail::protect_conversion<B>::type>      >    >,    typename return_type_2<Act, non_ref_A, non_ref_B>::type  >::RET type;};  // take care of the unavoidable instantiation for nullary casetemplate<class Act> struct return_type_2_prot<Act, null_type, null_type> {  typedef null_type type;};  // take care of the unavoidable instantiation for nullary casetemplate<class Act, class Other> struct return_type_2_prot<Act, Other, null_type> {  typedef null_type type;};  // take care of the unavoidable instantiation for nullary casetemplate<class Act, class Other> struct return_type_2_prot<Act, null_type, Other> {  typedef null_type type;};  // comma is a special case, as the user defined operator can return  // an lvalue (reference) too, hence it must be handled at this level.template<class A, class B> struct return_type_2_comma{  typedef typename boost::remove_reference<A>::type non_ref_A;  typedef typename boost::remove_reference<B>::type non_ref_B;typedef typename   detail::IF<//  is_protectable<other_action<comma_action> >::value && // it is protectable//  (is_lambda_functor<A>::value || is_lambda_functor<B>::value),    ice_and<is_protectable<other_action<comma_action> >::value, // it is protectable            ice_or<is_lambda_functor<A>::value,                    is_lambda_functor<B>::value>::value>::value,    lambda_functor<      lambda_functor_base<         other_action<comma_action>,         tuple<typename detail::protect_conversion<A>::type,               typename detail::protect_conversion<B>::type>      >    >,    typename       return_type_2<other_action<comma_action>, non_ref_A, non_ref_B>::type  >::RET type1;   // if no user defined return_type_2 (or plain_return_type_2) specialization  // matches, then return the righthand argument  typedef typename     detail::IF<      boost::is_same<type1, detail::unspecified>::value,       B,      type1    >::RET type;};  // currently there are no protectable actions with > 2 args  // Note, that if there will be, lambda_functor_base will have to be   // changed to not get rid of references in Args elementstemplate<class Act, class Args> struct return_type_N_prot {  typedef typename return_type_N<Act, Args>::type type;};  // take care of the unavoidable instantiation for nullary casetemplate<class Act> struct return_type_N_prot<Act, null_type> {  typedef null_type type;};// handle different kind of actions ------------------------  // use the return type given in the bind invocation as bind<Ret>(...)template<int I, class Args, class Ret> struct return_type_N<function_action<I, Ret>, Args> {   typedef Ret type;};// ::result_type supportnamespace detail{BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)template<class F> struct get_result_type{  typedef typename F::result_type type;};template<class F, class A> struct get_sig{  typedef typename function_adaptor<F>::template sig<A>::type type;};} // namespace detail  // Ret is detail::unspecified, so try to deduce return typetemplate<int I, class Args> struct return_type_N<function_action<I, detail::unspecified>, Args > {   // in the case of function action, the first element in Args is   // some type of function  typedef typename Args::head_type Func;  typedef typename detail::remove_reference_and_cv<Func>::type plain_Func;public:   // pass the function to function_adaptor, and get the return type from   // that  typedef typename detail::IF<    detail::has_result_type<plain_Func>::value,    detail::get_result_type<plain_Func>,    detail::get_sig<plain_Func, Args>  >::RET::type type;};} // namespace lambda} // namespace boost#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?