Chris@16
|
1 // (C) Copyright Gennadiy Rozental 2005-2008.
|
Chris@16
|
2 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
3 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
4 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
5
|
Chris@16
|
6 // See http://www.boost.org/libs/test for the library home page.
|
Chris@16
|
7 //
|
Chris@16
|
8 // File : $RCSfile$
|
Chris@16
|
9 //
|
Chris@101
|
10 // Version : $Revision$
|
Chris@16
|
11 //
|
Chris@16
|
12 // Description : facilities for named function parameters support
|
Chris@16
|
13 // ***************************************************************************
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_TEST_NAMED_PARAM_022505GER
|
Chris@16
|
16 #define BOOST_TEST_NAMED_PARAM_022505GER
|
Chris@16
|
17
|
Chris@16
|
18 // Boost
|
Chris@16
|
19 #include <boost/config.hpp>
|
Chris@16
|
20 #include <boost/detail/workaround.hpp>
|
Chris@16
|
21
|
Chris@16
|
22 // Boost.Test
|
Chris@16
|
23 #include <boost/test/utils/rtti.hpp>
|
Chris@16
|
24 #include <boost/test/utils/assign_op.hpp>
|
Chris@16
|
25
|
Chris@16
|
26 #include <boost/type_traits/remove_reference.hpp>
|
Chris@16
|
27
|
Chris@16
|
28 #include <boost/test/detail/suppress_warnings.hpp>
|
Chris@16
|
29
|
Chris@16
|
30 //____________________________________________________________________________//
|
Chris@16
|
31
|
Chris@16
|
32 namespace boost {
|
Chris@16
|
33
|
Chris@16
|
34 namespace nfp { // named function parameters
|
Chris@16
|
35
|
Chris@16
|
36 // ************************************************************************** //
|
Chris@16
|
37 // ************** forward declarations ************** //
|
Chris@16
|
38 // ************************************************************************** //
|
Chris@16
|
39
|
Chris@16
|
40 template<typename T, typename unique_id,typename RefType> struct named_parameter;
|
Chris@16
|
41 template<typename unique_id,bool required> struct keyword;
|
Chris@16
|
42
|
Chris@16
|
43 namespace nfp_detail {
|
Chris@16
|
44
|
Chris@16
|
45 template<typename NP1,typename NP2> struct named_parameter_combine;
|
Chris@16
|
46
|
Chris@16
|
47 // ************************************************************************** //
|
Chris@16
|
48 // ************** access_to_invalid_parameter ************** //
|
Chris@16
|
49 // ************************************************************************** //
|
Chris@16
|
50
|
Chris@16
|
51 struct access_to_invalid_parameter {};
|
Chris@16
|
52
|
Chris@16
|
53 //____________________________________________________________________________//
|
Chris@16
|
54
|
Chris@16
|
55 inline void
|
Chris@16
|
56 report_access_to_invalid_parameter()
|
Chris@16
|
57 {
|
Chris@16
|
58 throw access_to_invalid_parameter();
|
Chris@16
|
59 }
|
Chris@16
|
60
|
Chris@16
|
61 //____________________________________________________________________________//
|
Chris@16
|
62
|
Chris@16
|
63 // ************************************************************************** //
|
Chris@16
|
64 // ************** nil ************** //
|
Chris@16
|
65 // ************************************************************************** //
|
Chris@16
|
66
|
Chris@16
|
67 struct nil {
|
Chris@16
|
68 template<typename T>
|
Chris@16
|
69 #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC)
|
Chris@16
|
70 operator T() const
|
Chris@16
|
71 #else
|
Chris@16
|
72 operator T const&() const
|
Chris@16
|
73 #endif
|
Chris@16
|
74 { report_access_to_invalid_parameter(); static T* v = 0; return *v; }
|
Chris@16
|
75
|
Chris@16
|
76 template<typename T>
|
Chris@16
|
77 T any_cast() const
|
Chris@16
|
78 { report_access_to_invalid_parameter(); static typename remove_reference<T>::type* v = 0; return *v; }
|
Chris@16
|
79
|
Chris@16
|
80 template<typename Arg1>
|
Chris@16
|
81 nil operator()( Arg1 const& )
|
Chris@16
|
82 { report_access_to_invalid_parameter(); return nil(); }
|
Chris@16
|
83
|
Chris@16
|
84 template<typename Arg1,typename Arg2>
|
Chris@16
|
85 nil operator()( Arg1 const&, Arg2 const& )
|
Chris@16
|
86 { report_access_to_invalid_parameter(); return nil(); }
|
Chris@16
|
87
|
Chris@16
|
88 template<typename Arg1,typename Arg2,typename Arg3>
|
Chris@16
|
89 nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
|
Chris@16
|
90 { report_access_to_invalid_parameter(); return nil(); }
|
Chris@16
|
91
|
Chris@16
|
92 // Visitation support
|
Chris@16
|
93 template<typename Visitor>
|
Chris@16
|
94 void apply_to( Visitor& V ) const {}
|
Chris@16
|
95
|
Chris@16
|
96 static nil& inst() { static nil s_inst; return s_inst; }
|
Chris@16
|
97 private:
|
Chris@16
|
98 nil() {}
|
Chris@16
|
99 };
|
Chris@16
|
100
|
Chris@16
|
101 // ************************************************************************** //
|
Chris@16
|
102 // ************** named_parameter_base ************** //
|
Chris@16
|
103 // ************************************************************************** //
|
Chris@16
|
104
|
Chris@16
|
105 template<typename Derived>
|
Chris@16
|
106 struct named_parameter_base {
|
Chris@16
|
107 template<typename NP>
|
Chris@16
|
108 named_parameter_combine<NP,Derived>
|
Chris@16
|
109 operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
|
Chris@16
|
110 };
|
Chris@16
|
111
|
Chris@16
|
112 //____________________________________________________________________________//
|
Chris@16
|
113
|
Chris@16
|
114 // ************************************************************************** //
|
Chris@16
|
115 // ************** named_parameter_combine ************** //
|
Chris@16
|
116 // ************************************************************************** //
|
Chris@16
|
117
|
Chris@16
|
118 template<typename NP, typename Rest = nil>
|
Chris@16
|
119 struct named_parameter_combine
|
Chris@16
|
120 : Rest
|
Chris@16
|
121 , named_parameter_base<named_parameter_combine<NP,Rest> > {
|
Chris@16
|
122 typedef typename NP::ref_type res_type;
|
Chris@16
|
123 typedef named_parameter_combine<NP,Rest> self_type;
|
Chris@16
|
124
|
Chris@16
|
125 // Constructor
|
Chris@16
|
126 named_parameter_combine( NP const& np, Rest const& r )
|
Chris@16
|
127 : Rest( r )
|
Chris@16
|
128 , m_param( np )
|
Chris@16
|
129 {}
|
Chris@16
|
130
|
Chris@16
|
131 // Access methods
|
Chris@16
|
132 res_type operator[]( keyword<typename NP::id,true> kw ) const { return m_param[kw]; }
|
Chris@16
|
133 res_type operator[]( keyword<typename NP::id,false> kw ) const { return m_param[kw]; }
|
Chris@16
|
134 using Rest::operator[];
|
Chris@16
|
135
|
Chris@16
|
136 bool has( keyword<typename NP::id,false> kw ) const { return m_param.has( kw ); }
|
Chris@16
|
137 using Rest::has;
|
Chris@16
|
138
|
Chris@16
|
139 void erase( keyword<typename NP::id,false> kw ) const { m_param.erase( kw ); }
|
Chris@16
|
140 using Rest::erase;
|
Chris@16
|
141
|
Chris@16
|
142 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) || \
|
Chris@16
|
143 BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0610))
|
Chris@16
|
144 template<typename NP>
|
Chris@16
|
145 named_parameter_combine<NP,self_type> operator,( NP const& np ) const
|
Chris@16
|
146 { return named_parameter_combine<NP,self_type>( np, *this ); }
|
Chris@16
|
147 #else
|
Chris@16
|
148 using named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
|
Chris@16
|
149 #endif
|
Chris@16
|
150
|
Chris@16
|
151 // Visitation support
|
Chris@16
|
152 template<typename Visitor>
|
Chris@16
|
153 void apply_to( Visitor& V ) const
|
Chris@16
|
154 {
|
Chris@16
|
155 m_param.apply_to( V );
|
Chris@16
|
156
|
Chris@16
|
157 Rest::apply_to( V );
|
Chris@16
|
158 }
|
Chris@16
|
159 private:
|
Chris@16
|
160 // Data members
|
Chris@16
|
161 NP m_param;
|
Chris@16
|
162 };
|
Chris@16
|
163
|
Chris@16
|
164 } // namespace nfp_detail
|
Chris@16
|
165
|
Chris@16
|
166 // ************************************************************************** //
|
Chris@16
|
167 // ************** named_parameter ************** //
|
Chris@16
|
168 // ************************************************************************** //
|
Chris@16
|
169
|
Chris@16
|
170 template<typename T, typename unique_id,typename ReferenceType=T&>
|
Chris@16
|
171 struct named_parameter
|
Chris@16
|
172 : nfp_detail::named_parameter_base<named_parameter<T, unique_id,ReferenceType> >
|
Chris@16
|
173 {
|
Chris@16
|
174 typedef nfp_detail::nil nil_t;
|
Chris@16
|
175 typedef T data_type;
|
Chris@16
|
176 typedef ReferenceType ref_type;
|
Chris@16
|
177 typedef unique_id id;
|
Chris@16
|
178
|
Chris@16
|
179 // Constructor
|
Chris@16
|
180 explicit named_parameter( ref_type v )
|
Chris@16
|
181 : m_value( v )
|
Chris@16
|
182 , m_erased( false )
|
Chris@16
|
183 {}
|
Chris@16
|
184 named_parameter( named_parameter const& np )
|
Chris@16
|
185 : m_value( np.m_value )
|
Chris@16
|
186 , m_erased( np.m_erased )
|
Chris@16
|
187 {}
|
Chris@16
|
188
|
Chris@16
|
189 // Access methods
|
Chris@16
|
190 ref_type operator[]( keyword<unique_id,true> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; }
|
Chris@16
|
191 ref_type operator[]( keyword<unique_id,false> ) const { return m_erased ? nil_t::inst().template any_cast<ref_type>() : m_value; }
|
Chris@16
|
192 template<typename UnknownId>
|
Chris@16
|
193 nil_t operator[]( keyword<UnknownId,false> ) const { return nil_t::inst(); }
|
Chris@16
|
194
|
Chris@16
|
195 bool has( keyword<unique_id,false> ) const { return !m_erased; }
|
Chris@16
|
196 template<typename UnknownId>
|
Chris@16
|
197 bool has( keyword<UnknownId,false> ) const { return false; }
|
Chris@16
|
198
|
Chris@16
|
199 void erase( keyword<unique_id,false> ) const { m_erased = true; }
|
Chris@16
|
200 template<typename UnknownId>
|
Chris@16
|
201 void erase( keyword<UnknownId,false> ) const {}
|
Chris@16
|
202
|
Chris@16
|
203 // Visitation support
|
Chris@16
|
204 template<typename Visitor>
|
Chris@16
|
205 void apply_to( Visitor& V ) const
|
Chris@16
|
206 {
|
Chris@16
|
207 V.set_parameter( rtti::type_id<unique_id>(), m_value );
|
Chris@16
|
208 }
|
Chris@16
|
209
|
Chris@16
|
210 private:
|
Chris@16
|
211 // Data members
|
Chris@16
|
212 ref_type m_value;
|
Chris@16
|
213 mutable bool m_erased;
|
Chris@16
|
214 };
|
Chris@16
|
215
|
Chris@16
|
216 //____________________________________________________________________________//
|
Chris@16
|
217
|
Chris@16
|
218 // ************************************************************************** //
|
Chris@16
|
219 // ************** no_params ************** //
|
Chris@16
|
220 // ************************************************************************** //
|
Chris@16
|
221
|
Chris@16
|
222 namespace nfp_detail {
|
Chris@16
|
223 typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
|
Chris@16
|
224 } // namespace nfp_detail
|
Chris@16
|
225
|
Chris@16
|
226 namespace {
|
Chris@16
|
227 nfp_detail::no_params_type no_params( '\0' );
|
Chris@16
|
228 } // local namespace
|
Chris@16
|
229
|
Chris@16
|
230 //____________________________________________________________________________//
|
Chris@16
|
231
|
Chris@16
|
232 // ************************************************************************** //
|
Chris@16
|
233 // ************** keyword ************** //
|
Chris@16
|
234 // ************************************************************************** //
|
Chris@16
|
235
|
Chris@16
|
236 template<typename unique_id, bool required = false>
|
Chris@16
|
237 struct keyword {
|
Chris@16
|
238 typedef unique_id id;
|
Chris@16
|
239
|
Chris@16
|
240 template<typename T>
|
Chris@16
|
241 named_parameter<T const,unique_id>
|
Chris@16
|
242 operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
|
Chris@16
|
243
|
Chris@16
|
244 template<typename T>
|
Chris@16
|
245 named_parameter<T,unique_id>
|
Chris@16
|
246 operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
|
Chris@16
|
247
|
Chris@16
|
248 named_parameter<char const*,unique_id,char const*>
|
Chris@16
|
249 operator=( char const* t ) const { return named_parameter<char const*,unique_id,char const*>( t ); }
|
Chris@16
|
250 };
|
Chris@16
|
251
|
Chris@16
|
252 //____________________________________________________________________________//
|
Chris@16
|
253
|
Chris@16
|
254 // ************************************************************************** //
|
Chris@16
|
255 // ************** typed_keyword ************** //
|
Chris@16
|
256 // ************************************************************************** //
|
Chris@16
|
257
|
Chris@16
|
258 template<typename T, typename unique_id, bool required = false>
|
Chris@16
|
259 struct typed_keyword : keyword<unique_id,required> {
|
Chris@16
|
260 named_parameter<T const,unique_id>
|
Chris@16
|
261 operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
|
Chris@16
|
262
|
Chris@16
|
263 named_parameter<T,unique_id>
|
Chris@16
|
264 operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
|
Chris@16
|
265 };
|
Chris@16
|
266
|
Chris@16
|
267 //____________________________________________________________________________//
|
Chris@16
|
268
|
Chris@16
|
269 template<typename unique_id>
|
Chris@16
|
270 struct typed_keyword<bool,unique_id,false>
|
Chris@16
|
271 : keyword<unique_id,false>
|
Chris@16
|
272 , named_parameter<bool,unique_id,bool> {
|
Chris@16
|
273 typedef unique_id id;
|
Chris@16
|
274
|
Chris@16
|
275 typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
|
Chris@16
|
276
|
Chris@16
|
277 named_parameter<bool,unique_id,bool>
|
Chris@16
|
278 operator!() const { return named_parameter<bool,unique_id,bool>( false ); }
|
Chris@16
|
279 };
|
Chris@16
|
280
|
Chris@16
|
281 //____________________________________________________________________________//
|
Chris@16
|
282
|
Chris@16
|
283 // ************************************************************************** //
|
Chris@16
|
284 // ************** optionally_assign ************** //
|
Chris@16
|
285 // ************************************************************************** //
|
Chris@16
|
286
|
Chris@16
|
287 template<typename T>
|
Chris@16
|
288 inline void
|
Chris@16
|
289 optionally_assign( T&, nfp_detail::nil )
|
Chris@16
|
290 {
|
Chris@16
|
291 nfp_detail::report_access_to_invalid_parameter();
|
Chris@16
|
292 }
|
Chris@16
|
293
|
Chris@16
|
294 //____________________________________________________________________________//
|
Chris@16
|
295
|
Chris@16
|
296 template<typename T, typename Source>
|
Chris@16
|
297 inline void
|
Chris@16
|
298 #if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \
|
Chris@16
|
299 || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) )
|
Chris@16
|
300 optionally_assign( T& target, Source src )
|
Chris@16
|
301 #else
|
Chris@16
|
302 optionally_assign( T& target, Source const& src )
|
Chris@16
|
303 #endif
|
Chris@16
|
304 {
|
Chris@16
|
305 using namespace unit_test;
|
Chris@16
|
306
|
Chris@16
|
307 assign_op( target, src, static_cast<int>(0) );
|
Chris@16
|
308 }
|
Chris@16
|
309
|
Chris@16
|
310 //____________________________________________________________________________//
|
Chris@16
|
311
|
Chris@16
|
312 template<typename T, typename Params, typename Keyword>
|
Chris@16
|
313 inline void
|
Chris@16
|
314 optionally_assign( T& target, Params const& p, Keyword k )
|
Chris@16
|
315 {
|
Chris@16
|
316 if( p.has(k) )
|
Chris@16
|
317 optionally_assign( target, p[k] );
|
Chris@16
|
318 }
|
Chris@16
|
319
|
Chris@16
|
320 //____________________________________________________________________________//
|
Chris@16
|
321
|
Chris@16
|
322 } // namespace nfp
|
Chris@16
|
323
|
Chris@16
|
324 } // namespace boost
|
Chris@16
|
325
|
Chris@16
|
326 #include <boost/test/detail/enable_warnings.hpp>
|
Chris@16
|
327
|
Chris@16
|
328 #endif // BOOST_TEST_NAMED_PARAM_022505GER
|
Chris@16
|
329
|