1 // Copyright Daniel Wallin, David Abrahams 2005. Use, modification and 2 // distribution is subject to the Boost Software License, Version 1.0. (See 3 // accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP 7 # define BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP 8 9 # include <boost/parameter/aux_/void.hpp> 10 # include <boost/parameter/aux_/arg_list.hpp> 11 # include <boost/parameter/aux_/result_of0.hpp> 12 # include <boost/mpl/if.hpp> 13 # include <boost/mpl/apply_wrap.hpp> 14 # include <boost/mpl/and.hpp> 15 # include <boost/mpl/not.hpp> 16 # include <boost/type_traits/is_same.hpp> 17 # include <boost/type_traits/is_convertible.hpp> 18 # include <boost/type_traits/is_reference.hpp> 19 20 namespace boost { namespace parameter { namespace aux { 21 22 struct empty_arg_list; 23 struct arg_list_tag; 24 25 struct tagged_argument_base {}; 26 27 // Holds a reference to an argument of type Arg associated with 28 // keyword Keyword 29 30 template <class Keyword, class Arg> 31 struct tagged_argument : tagged_argument_base 32 { 33 typedef Keyword key_type; 34 typedef Arg value_type; 35 typedef Arg& reference; 36 tagged_argumentboost::parameter::aux::tagged_argument37 tagged_argument(reference x) : value(x) {} 38 39 // A metafunction class that, given a keyword and a default 40 // type, returns the appropriate result type for a keyword 41 // lookup given that default 42 struct binding 43 { 44 template <class KW, class Default, class Reference> 45 struct apply 46 { 47 typedef typename mpl::eval_if< 48 boost::is_same<KW, key_type> 49 , mpl::if_<Reference, reference, value_type> 50 , mpl::identity<Default> 51 >::type type; 52 }; 53 }; 54 55 // Comma operator to compose argument list without using parameters<>. 56 // Useful for argument lists with undetermined length. 57 template <class Keyword2, class Arg2> 58 arg_list< 59 tagged_argument<Keyword, Arg> 60 , arg_list<tagged_argument<Keyword2, Arg2> > 61 > operator ,boost::parameter::aux::tagged_argument62 operator,(tagged_argument<Keyword2, Arg2> x) const 63 { 64 return arg_list< 65 tagged_argument<Keyword, Arg> 66 , arg_list<tagged_argument<Keyword2, Arg2> > 67 >( 68 *this 69 , arg_list<tagged_argument<Keyword2, Arg2> >(x, empty_arg_list()) 70 ); 71 } 72 operator []boost::parameter::aux::tagged_argument73 reference operator[](keyword<Keyword> const&) const 74 { 75 return value; 76 } 77 78 # if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 79 template <class KW, class Default> get_with_defaultboost::parameter::aux::tagged_argument80 Default& get_with_default(default_<KW,Default> const& x, int) const 81 { 82 return x.value; 83 } 84 85 template <class Default> get_with_defaultboost::parameter::aux::tagged_argument86 reference get_with_default(default_<key_type,Default> const&, long) const 87 { 88 return value; 89 } 90 91 template <class KW, class Default> 92 typename mpl::apply_wrap3<binding, KW, Default&, mpl::true_>::type operator []boost::parameter::aux::tagged_argument93 operator[](default_<KW,Default> const& x) const 94 { 95 return get_with_default(x, 0L); 96 } 97 98 template <class KW, class F> 99 typename result_of0<F>::type get_with_lazy_defaultboost::parameter::aux::tagged_argument100 get_with_lazy_default(lazy_default<KW,F> const& x, int) const 101 { 102 return x.compute_default(); 103 } 104 105 template <class F> get_with_lazy_defaultboost::parameter::aux::tagged_argument106 reference get_with_lazy_default(lazy_default<key_type,F> const&, long) const 107 { 108 return value; 109 } 110 111 template <class KW, class F> 112 typename mpl::apply_wrap3< 113 binding,KW 114 , typename result_of0<F>::type 115 , mpl::true_ 116 >::type operator []boost::parameter::aux::tagged_argument117 operator[](lazy_default<KW,F> const& x) const 118 { 119 return get_with_lazy_default(x, 0L); 120 } 121 # else 122 template <class Default> operator []boost::parameter::aux::tagged_argument123 reference operator[](default_<key_type,Default> const& ) const 124 { 125 return value; 126 } 127 128 template <class F> operator []boost::parameter::aux::tagged_argument129 reference operator[](lazy_default<key_type,F> const& ) const 130 { 131 return value; 132 } 133 134 template <class KW, class Default> operator []boost::parameter::aux::tagged_argument135 Default& operator[](default_<KW,Default> const& x) const 136 { 137 return x.value; 138 } 139 140 template <class KW, class F> operator []boost::parameter::aux::tagged_argument141 typename result_of0<F>::type operator[](lazy_default<KW,F> const& x) const 142 { 143 return x.compute_default(); 144 } 145 146 template <class ParameterRequirements> 147 static typename ParameterRequirements::has_default 148 satisfies(ParameterRequirements*); 149 150 template <class HasDefault, class Predicate> 151 static typename mpl::apply1<Predicate, value_type>::type 152 satisfies( 153 parameter_requirements<key_type,Predicate,HasDefault>* 154 ); 155 # endif 156 157 reference value; 158 # if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) 159 // warning suppression 160 private: 161 void operator=(tagged_argument const&); 162 public: 163 # endif 164 // MPL sequence support 165 typedef tagged_argument type; // Convenience for users 166 typedef empty_arg_list tail_type; // For the benefit of iterators 167 typedef arg_list_tag tag; // For dispatching to sequence intrinsics 168 }; 169 170 // Defines a metafunction, is_tagged_argument, that identifies 171 // tagged_argument specializations and their derived classes. 172 template <class T> 173 struct is_tagged_argument_aux 174 : is_convertible<T*,tagged_argument_base const*> 175 {}; 176 177 template <class T> 178 struct is_tagged_argument 179 : mpl::and_< 180 mpl::not_<is_reference<T> > 181 , is_tagged_argument_aux<T> 182 > 183 {}; 184 185 }}} // namespace boost::parameter::aux 186 187 #endif // BOOST_PARAMETER_TAGGED_ARGUMENT_050328_HPP 188 189