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