| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 | // - lambda_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_LAMBDA_TRAITS_HPP#define BOOST_LAMBDA_LAMBDA_TRAITS_HPP#include "boost/type_traits/transform_traits.hpp"#include "boost/type_traits/cv_traits.hpp"#include "boost/type_traits/function_traits.hpp"#include "boost/type_traits/object_traits.hpp"#include "boost/tuple/tuple.hpp"namespace boost {namespace lambda {// -- if construct ------------------------------------------------// Proposed by Krzysztof Czarnecki and Ulrich Eiseneckernamespace detail {template <bool If, class Then, class Else> struct IF { typedef Then RET; };template <class Then, class Else> struct IF<false, Then, Else> {  typedef Else RET;};// An if construct that doesn't instantiate the non-matching template:// Called as: //  IF_type<condition, A, B>::type // The matching template must define the typeded 'type'// I.e. A::type if condition is true, B::type if condition is false// Idea from Vesa Karvonen (from C&E as well I guess)template<class T>struct IF_type_{  typedef typename T::type type;};template<bool C, class T, class E>struct IF_type{  typedef typename    IF_type_<typename IF<C, T, E>::RET >::type type;};// helper that can be used to give typedef T to some typetemplate <class T> struct identity_mapping { typedef T type; };// An if construct for finding an integral constant 'value'// Does not instantiate the non-matching branch// Called as IF_value<condition, A, B>::value// If condition is true A::value must be defined, otherwise B::valuetemplate<class T>struct IF_value_{  BOOST_STATIC_CONSTANT(int, value = T::value);};template<bool C, class T, class E>struct IF_value{  BOOST_STATIC_CONSTANT(int, value = (IF_value_<typename IF<C, T, E>::RET>::value));};// --------------------------------------------------------------// removes reference from other than function types:template<class T> class remove_reference_if_valid{  typedef typename boost::remove_reference<T>::type plainT;public:  typedef typename IF<    boost::is_function<plainT>::value,    T,    plainT  >::RET type;};template<class T> struct remove_reference_and_cv {   typedef typename boost::remove_cv<     typename boost::remove_reference<T>::type   >::type type;};   // returns a reference to the element of tuple Ttemplate<int N, class T> struct tuple_element_as_reference {     typedef typename     boost::tuples::access_traits<       typename boost::tuples::element<N, T>::type     >::non_const_type type;};// returns the cv and reverence stripped type of a tuple elementtemplate<int N, class T> struct tuple_element_stripped {     typedef typename     remove_reference_and_cv<       typename boost::tuples::element<N, T>::type     >::type type;};// is_lambda_functor -------------------------------------------------   template <class T> struct is_lambda_functor_ {  BOOST_STATIC_CONSTANT(bool, value = false);};   template <class Arg> struct is_lambda_functor_<lambda_functor<Arg> > {  BOOST_STATIC_CONSTANT(bool, value = true);};   } // end detail   template <class T> struct is_lambda_functor {  BOOST_STATIC_CONSTANT(bool,      value =        detail::is_lambda_functor_<         typename detail::remove_reference_and_cv<T>::type       >::value);};   namespace detail {// -- parameter_traits_ ---------------------------------------------// An internal parameter type traits class that respects// the reference_wrapper class.// The conversions performed are:// references -> compile_time_error// T1 -> T2, // reference_wrapper<T> -> T&// const array -> ref to const array// array -> ref to array// function -> ref to function// ------------------------------------------------------------------------template<class T1, class T2> struct parameter_traits_ {  typedef T2 type;};// Do not instantiate with reference typestemplate<class T, class Any> struct parameter_traits_<T&, Any> {  typedef typename     generate_error<T&>::      parameter_traits_class_instantiated_with_reference_type type;};// Arrays can't be stored as plain types; convert them to referencestemplate<class T, int n, class Any> struct parameter_traits_<T[n], Any> {  typedef T (&type)[n];};   template<class T, int n, class Any> struct parameter_traits_<const T[n], Any> {  typedef const T (&type)[n];};template<class T, int n, class Any> struct parameter_traits_<volatile T[n], Any> {  typedef volatile  T (&type)[n];};template<class T, int n, class Any> struct parameter_traits_<const volatile T[n], Any> {  typedef const volatile T (&type)[n];};template<class T, class Any> struct parameter_traits_<boost::reference_wrapper<T>, Any >{  typedef T& type;};template<class T, class Any> struct parameter_traits_<const boost::reference_wrapper<T>, Any >{  typedef T& type;};template<class T, class Any> struct parameter_traits_<volatile boost::reference_wrapper<T>, Any >{  typedef T& type;};template<class T, class Any> struct parameter_traits_<const volatile boost::reference_wrapper<T>, Any >{  typedef T& type;};template<class Any>struct parameter_traits_<void, Any> {  typedef void type;};template<class Arg, class Any>struct parameter_traits_<lambda_functor<Arg>, Any > {  typedef lambda_functor<Arg> type;};template<class Arg, class Any>struct parameter_traits_<const lambda_functor<Arg>, Any > {  typedef lambda_functor<Arg> type;};// Are the volatile versions needed?template<class Arg, class Any>struct parameter_traits_<volatile lambda_functor<Arg>, Any > {  typedef lambda_functor<Arg> type;};template<class Arg, class Any>struct parameter_traits_<const volatile lambda_functor<Arg>, Any > {  typedef lambda_functor<Arg> type;};} // end namespace detail// ------------------------------------------------------------------------// traits classes for lambda expressions (bind functions, operators ...)   // must be instantiated with non-reference types// The default is const plain type -------------------------// const T -> const T, // T -> const T, // references -> compile_time_error// reference_wrapper<T> -> T&// array -> const ref arraytemplate<class T>struct const_copy_argument {  typedef typename     detail::parameter_traits_<      T,      typename detail::IF<boost::is_function<T>::value, T&, const T>::RET    >::type type;};// T may be a function type. Without the IF test, const would be added // to a function type, which is illegal.// all arrays are converted to const.// This traits template is used for 'const T&' parameter passing // and thus the knowledge of the potential // non-constness of an actual argument is lost.   template<class T, int n>  struct const_copy_argument <T[n]> {  typedef const T (&type)[n];};template<class T, int n>  struct const_copy_argument <volatile T[n]> {     typedef const volatile T (&type)[n];};   template<class T>struct const_copy_argument<T&> {};// do not instantiate with references  //  typedef typename detail::generate_error<T&>::references_not_allowed type;template<>struct const_copy_argument<void> {  typedef void type;};template<>struct const_copy_argument<void const> {  typedef void type;};// Does the same as const_copy_argument, but passes references through as suchtemplate<class T>struct bound_argument_conversion {  typedef typename const_copy_argument<T>::type type; };template<class T>struct bound_argument_conversion<T&> {  typedef T& type; };   // The default is non-const reference -------------------------// const T -> const T&, // T -> T&, // references -> compile_time_error// reference_wrapper<T> -> T&template<class T>struct reference_argument {  typedef typename detail::parameter_traits_<T, T&>::type type; };template<class T>struct reference_argument<T&> {  typedef typename detail::generate_error<T&>::references_not_allowed type; };template<class Arg>struct reference_argument<lambda_functor<Arg> > {  typedef lambda_functor<Arg> type;};template<class Arg>struct reference_argument<const lambda_functor<Arg> > {  typedef lambda_functor<Arg> type;};// Are the volatile versions needed?template<class Arg>struct reference_argument<volatile lambda_functor<Arg> > {  typedef lambda_functor<Arg> type;};template<class Arg>struct reference_argument<const volatile lambda_functor<Arg> > {  typedef lambda_functor<Arg> type;};template<>struct reference_argument<void> {  typedef void type;};namespace detail {   // Array to pointer conversiontemplate <class T>struct array_to_pointer {   typedef T type;};template <class T, int N>struct array_to_pointer <const T[N]> {   typedef const T* type;};template <class T, int N>struct array_to_pointer <T[N]> {   typedef T* type;};template <class T, int N>struct array_to_pointer <const T (&) [N]> {   typedef const T* type;};template <class T, int N>struct array_to_pointer <T (&) [N]> {   typedef T* type;};// ---------------------------------------------------------------------------// The call_traits for bind// Respects the reference_wrapper class.// These templates are used outside of bind functions as well.// the bind_tuple_mapper provides a shorter notation for default// bound argument storing semantics, if all arguments are treated// uniformly.// from template<class T> foo(const T& t) : bind_traits<const T>::type// from template<class T> foo(T& t) : bind_traits<T>::type// Conversions:// T -> const T,// cv T -> cv T, // T& -> T& // reference_wrapper<T> -> T&// const reference_wrapper<T> -> T&// array -> const ref array// make bound arguments const, this is a deliberate design choice, the// purpose is to prevent side effects to bound arguments that are stored// as copiestemplate<class T>struct bind_traits {  typedef const T type; };template<class T>struct bind_traits<T&> {  typedef T& type; };// null_types are an exception, we always want to store them as non const// so that other templates can assume that null_type is always without consttemplate<>struct bind_traits<null_type> {  typedef null_type type;};// the bind_tuple_mapper, bind_type_generators may // introduce const to null_typetemplate<>struct bind_traits<const null_type> {  typedef null_type type;};// Arrays can't be stored as plain types; convert them to references.// All arrays are converted to const. This is because bind takes its// parameters as const T& and thus the knowledge of the potential // non-constness of actual argument is lost.template<class T, int n>  struct bind_traits <T[n]> {  typedef const T (&type)[n];};template<class T, int n> struct bind_traits<const T[n]> {  typedef const T (&type)[n];};template<class T, int n>  struct bind_traits<volatile T[n]> {  typedef const volatile T (&type)[n];};template<class T, int n> struct bind_traits<const volatile T[n]> {  typedef const volatile T (&type)[n];};template<class R>struct bind_traits<R()> {    typedef R(&type)();};template<class R, class Arg1>struct bind_traits<R(Arg1)> {    typedef R(&type)(Arg1);};template<class R, class Arg1, class Arg2>struct bind_traits<R(Arg1, Arg2)> {    typedef R(&type)(Arg1, Arg2);};template<class R, class Arg1, class Arg2, class Arg3>struct bind_traits<R(Arg1, Arg2, Arg3)> {    typedef R(&type)(Arg1, Arg2, Arg3);};template<class R, class Arg1, class Arg2, class Arg3, class Arg4>struct bind_traits<R(Arg1, Arg2, Arg3, Arg4)> {    typedef R(&type)(Arg1, Arg2, Arg3, Arg4);};template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5>struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5)> {    typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5);};template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6>struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> {    typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);};template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7>struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)> {    typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7);};template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8>struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)> {    typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8);};template<class R, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, class Arg6, class Arg7, class Arg8, class Arg9>struct bind_traits<R(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9)> {    typedef R(&type)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9);};template<class T> struct bind_traits<reference_wrapper<T> >{  typedef T& type;};template<class T> struct bind_traits<const reference_wrapper<T> >{  typedef T& type;};template<>struct bind_traits<void> {  typedef void type;};template <  class T0 = null_type, class T1 = null_type, class T2 = null_type,   class T3 = null_type, class T4 = null_type, class T5 = null_type,   class T6 = null_type, class T7 = null_type, class T8 = null_type,   class T9 = null_type>struct bind_tuple_mapper {  typedef    tuple<typename bind_traits<T0>::type,           typename bind_traits<T1>::type,           typename bind_traits<T2>::type,           typename bind_traits<T3>::type,           typename bind_traits<T4>::type,           typename bind_traits<T5>::type,           typename bind_traits<T6>::type,           typename bind_traits<T7>::type,          typename bind_traits<T8>::type,          typename bind_traits<T9>::type> type;};// bind_traits, except map const T& -> const T  // this is needed e.g. in currying. Const reference arguments can  // refer to temporaries, so it is not safe to store them as references.  template <class T> struct remove_const_reference {    typedef typename bind_traits<T>::type type;  };  template <class T> struct remove_const_reference<const T&> {    typedef const T type;  };// maps the bind argument types to the resulting lambda functor typetemplate <  class T0 = null_type, class T1 = null_type, class T2 = null_type,   class T3 = null_type, class T4 = null_type, class T5 = null_type,   class T6 = null_type, class T7 = null_type, class T8 = null_type,   class T9 = null_type>class bind_type_generator {  typedef typename  detail::bind_tuple_mapper<    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9  >::type args_t;  BOOST_STATIC_CONSTANT(int, nof_elems = boost::tuples::length<args_t>::value);  typedef     action<      nof_elems,       function_action<nof_elems>    > action_type;public:  typedef    lambda_functor<      lambda_functor_base<        action_type,         args_t      >    > type;     };   } // detail   template <class T> inline const T&  make_const(const T& t) { return t; }} // end of namespace lambda} // end of namespace boost   #endif // BOOST_LAMBDA_TRAITS_HPP
 |