Line data Source code
1 : // (C) Copyright Gennadiy Rozental 2001.
2 : // Distributed under the Boost Software License, Version 1.0.
3 : // (See accompanying file LICENSE_1_0.txt or copy at
4 : // http://www.boost.org/LICENSE_1_0.txt)
5 :
6 : // See http://www.boost.org/libs/test for the library home page.
7 : //
8 : // File : $RCSfile$
9 : //
10 : // Version : $Revision$
11 : //
12 : // Description : named function parameters library
13 : // ***************************************************************************
14 :
15 : #ifndef BOOST_TEST_UTILS_NAMED_PARAM
16 : #define BOOST_TEST_UTILS_NAMED_PARAM
17 :
18 : // Boost
19 : #include <boost/config.hpp>
20 : #include <boost/detail/workaround.hpp>
21 :
22 : // Boost.Test
23 : #include <boost/test/utils/rtti.hpp>
24 : #include <boost/test/utils/assign_op.hpp>
25 :
26 : #include <boost/type_traits/remove_reference.hpp>
27 : #include <boost/type_traits/remove_cv.hpp>
28 :
29 : #include <boost/test/detail/throw_exception.hpp>
30 :
31 : // Boost
32 : #include <boost/mpl/if.hpp>
33 : #include <boost/mpl/or.hpp>
34 : #include <boost/type_traits/is_same.hpp>
35 : #include <boost/type_traits/remove_cv.hpp>
36 : #include <boost/utility/enable_if.hpp>
37 : #include <boost/mpl/bool.hpp>
38 :
39 : #include <boost/test/detail/suppress_warnings.hpp>
40 :
41 : //____________________________________________________________________________//
42 :
43 : namespace boost {
44 : namespace nfp { // named function parameters
45 :
46 : // ************************************************************************** //
47 : // ************** forward declarations ************** //
48 : // ************************************************************************** //
49 :
50 : template<typename unique_id, bool required> struct keyword;
51 : template<typename T, typename unique_id, bool required = false> struct typed_keyword;
52 :
53 : template<typename T, typename unique_id, typename RefType=T&> struct named_parameter;
54 : template<typename NP1,typename NP2> struct named_parameter_combine;
55 :
56 : // ************************************************************************** //
57 : // ************** is_named_param_pack ************** //
58 : // ************************************************************************** //
59 :
60 : /// is_named_param_pack<T>::value is true if T is parameters pack
61 :
62 : template<typename T>
63 : struct is_named_param_pack : public mpl::false_ {};
64 :
65 : template<typename T, typename unique_id, typename RefType>
66 : struct is_named_param_pack<named_parameter<T,unique_id,RefType> > : public mpl::true_ {};
67 :
68 : template<typename NP, typename Rest>
69 : struct is_named_param_pack<named_parameter_combine<NP,Rest> > : public mpl::true_ {};
70 :
71 : // ************************************************************************** //
72 : // ************** param_type ************** //
73 : // ************************************************************************** //
74 :
75 : /// param_type<Params,Keyword,Default>::type is the type of the parameter
76 : /// corresponding to the Keyword (if parameter is present) or Default
77 :
78 : template<typename NP, typename Keyword, typename DefaultType=void>
79 : struct param_type
80 : : mpl::if_<typename is_same<typename NP::id,typename Keyword::id>::type,
81 : typename remove_cv<typename NP::data_type>::type,
82 : DefaultType> {};
83 :
84 : template<typename NP, typename Rest, typename Keyword, typename DefaultType>
85 : struct param_type<named_parameter_combine<NP,Rest>,Keyword,DefaultType>
86 : : mpl::if_<typename is_same<typename NP::id,typename Keyword::id>::type,
87 : typename remove_cv<typename NP::data_type>::type,
88 : typename param_type<Rest,Keyword,DefaultType>::type> {};
89 :
90 : // ************************************************************************** //
91 : // ************** has_param ************** //
92 : // ************************************************************************** //
93 :
94 : /// has_param<Params,Keyword>::value is true if Params has parameter corresponding
95 : /// to the Keyword
96 :
97 : template<typename NP, typename Keyword>
98 : struct has_param : is_same<typename NP::id,typename Keyword::id> {};
99 :
100 : template<typename NP, typename Rest, typename Keyword>
101 : struct has_param<named_parameter_combine<NP,Rest>,Keyword>
102 : : mpl::or_<typename is_same<typename NP::id,typename Keyword::id>::type,
103 : typename has_param<Rest,Keyword>::type> {};
104 :
105 : // ************************************************************************** //
106 : // ************** access_to_invalid_parameter ************** //
107 : // ************************************************************************** //
108 :
109 : namespace nfp_detail {
110 :
111 : struct access_to_invalid_parameter {};
112 :
113 : //____________________________________________________________________________//
114 :
115 : inline void
116 0 : report_access_to_invalid_parameter( bool v )
117 : {
118 0 : BOOST_TEST_I_ASSRT( !v, access_to_invalid_parameter() );
119 0 : }
120 :
121 : } // namespace nfp_detail
122 :
123 : // ************************************************************************** //
124 : // ************** nil ************** //
125 : // ************************************************************************** //
126 :
127 : struct nil {
128 : template<typename T>
129 : #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC) || defined(BOOST_EMBTC)
130 : operator T() const
131 : #else
132 : operator T const&() const
133 : #endif
134 : { nfp_detail::report_access_to_invalid_parameter(true); BOOST_TEST_UNREACHABLE_RETURN(*static_cast<T*>(0)); }
135 :
136 : template<typename T>
137 0 : T any_cast() const
138 0 : { nfp_detail::report_access_to_invalid_parameter(true); BOOST_TEST_UNREACHABLE_RETURN(*static_cast<typename std::remove_reference<T>::type*>(0)); }
139 :
140 : template<typename Arg1>
141 : nil operator()( Arg1 const& )
142 : { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
143 :
144 : template<typename Arg1,typename Arg2>
145 : nil operator()( Arg1 const&, Arg2 const& )
146 : { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
147 :
148 : template<typename Arg1,typename Arg2,typename Arg3>
149 : nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
150 : { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
151 :
152 : // Visitation support
153 : template<typename Visitor>
154 : void apply_to( Visitor& /*v*/ ) const {}
155 :
156 0 : static nil& inst() { static nil s_inst; return s_inst; }
157 : private:
158 0 : nil() {}
159 : };
160 :
161 : // ************************************************************************** //
162 : // ************** named_parameter_base ************** //
163 : // ************************************************************************** //
164 :
165 : namespace nfp_detail {
166 :
167 : template<typename Derived>
168 : struct named_parameter_base {
169 : template<typename NP>
170 : named_parameter_combine<NP,Derived>
171 18834 : operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
172 : };
173 :
174 : } // namespace nfp_detail
175 :
176 : // ************************************************************************** //
177 : // ************** named_parameter_combine ************** //
178 : // ************************************************************************** //
179 :
180 : template<typename NP, typename Rest = nil>
181 : struct named_parameter_combine
182 : : Rest
183 : , nfp_detail::named_parameter_base<named_parameter_combine<NP,Rest> > {
184 : typedef typename NP::ref_type res_type;
185 : typedef named_parameter_combine<NP,Rest> self_type;
186 :
187 : // Constructor
188 37668 : named_parameter_combine( NP const& np, Rest const& r )
189 18834 : : Rest( r )
190 18834 : , m_param( np )
191 18834 : {
192 37668 : }
193 :
194 : // Access methods
195 : res_type operator[]( keyword<typename NP::id,true> kw ) const { return m_param[kw]; }
196 16498 : res_type operator[]( keyword<typename NP::id,false> kw ) const { return m_param[kw]; }
197 : using Rest::operator[];
198 :
199 7738 : bool has( keyword<typename NP::id,false> kw ) const { return m_param.has( kw ); }
200 : using Rest::has;
201 :
202 : void erase( keyword<typename NP::id,false> kw ) const { m_param.erase( kw ); }
203 : using Rest::erase;
204 :
205 : using nfp_detail::named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
206 :
207 : // Visitation support
208 : template<typename Visitor>
209 : void apply_to( Visitor& V ) const
210 : {
211 : m_param.apply_to( V );
212 :
213 : Rest::apply_to( V );
214 : }
215 : private:
216 : // Data members
217 : NP m_param;
218 : };
219 :
220 : // ************************************************************************** //
221 : // ************** named_parameter ************** //
222 : // ************************************************************************** //
223 :
224 : template<typename T, typename unique_id, typename RefType>
225 : struct named_parameter
226 : : nfp_detail::named_parameter_base<named_parameter<T,unique_id,RefType> >
227 : {
228 : typedef T data_type;
229 : typedef RefType ref_type;
230 : typedef unique_id id;
231 :
232 : // Constructor
233 49786 : explicit named_parameter( ref_type v )
234 24966 : : m_value( v )
235 24966 : , m_erased( false )
236 49786 : {}
237 124246 : named_parameter( named_parameter const& np )
238 72124 : : m_value( np.m_value )
239 72124 : , m_erased( np.m_erased )
240 124246 : {}
241 :
242 : // Access methods
243 : ref_type operator[]( keyword<unique_id,true> ) const { return m_erased ? nil::inst().template any_cast<ref_type>() : m_value; }
244 21170 : ref_type operator[]( keyword<unique_id,false> ) const { return m_erased ? nil::inst().template any_cast<ref_type>() : m_value; }
245 : template<typename UnknownId>
246 : nil operator[]( keyword<UnknownId,false> ) const { return nil::inst(); }
247 :
248 8176 : bool has( keyword<unique_id,false> ) const { return !m_erased; }
249 : template<typename UnknownId>
250 5694 : bool has( keyword<UnknownId,false> ) const { return false; }
251 :
252 : void erase( keyword<unique_id,false> ) const { m_erased = true; }
253 : template<typename UnknownId>
254 : void erase( keyword<UnknownId,false> ) const {}
255 :
256 : // Visitation support
257 : template<typename Visitor>
258 : void apply_to( Visitor& V ) const
259 : {
260 : V.set_parameter( rtti::type_id<unique_id>(), m_value );
261 : }
262 :
263 : private:
264 : // Data members
265 : ref_type m_value;
266 : mutable bool m_erased;
267 : };
268 :
269 : // ************************************************************************** //
270 : // ************** no_params ************** //
271 : // ************************************************************************** //
272 :
273 : typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
274 :
275 : namespace {
276 : no_params_type no_params( '\0' );
277 : } // local namespace
278 :
279 : // ************************************************************************** //
280 : // ************** keyword ************** //
281 : // ************************************************************************** //
282 :
283 : template<typename unique_id, bool required = false>
284 : struct keyword {
285 : typedef unique_id id;
286 :
287 : template<typename T>
288 : named_parameter<T const,unique_id>
289 10512 : operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
290 :
291 : template<typename T>
292 : named_parameter<T,unique_id>
293 : operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
294 :
295 : named_parameter<char const*,unique_id,char const*>
296 438 : operator=( char const* t ) const { return named_parameter<char const*,unique_id,char const*>( t ); }
297 : };
298 :
299 : //____________________________________________________________________________//
300 :
301 : // ************************************************************************** //
302 : // ************** typed_keyword ************** //
303 : // ************************************************************************** //
304 :
305 : template<typename T, typename unique_id, bool required>
306 : struct typed_keyword : keyword<unique_id,required> {
307 : named_parameter<T const,unique_id>
308 13724 : operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
309 :
310 : named_parameter<T,unique_id>
311 : operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
312 : };
313 :
314 : //____________________________________________________________________________//
315 :
316 : template<typename unique_id, bool required>
317 : struct typed_keyword<bool,unique_id,required>
318 : : keyword<unique_id,required>
319 : , named_parameter<bool,unique_id,bool> {
320 : typedef unique_id id;
321 :
322 292 : typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
323 :
324 : named_parameter<bool,unique_id,bool>
325 : operator!() const { return named_parameter<bool,unique_id,bool>( false ); }
326 : };
327 :
328 : // ************************************************************************** //
329 : // ************** opt_assign ************** //
330 : // ************************************************************************** //
331 :
332 : template<typename T, typename Params, typename Keyword>
333 : inline typename enable_if_c<!has_param<Params,Keyword>::value,void>::type
334 10220 : opt_assign( T& /*target*/, Params const& /*p*/, Keyword /*k*/ )
335 : {
336 10220 : }
337 :
338 : //____________________________________________________________________________//
339 :
340 : template<typename T, typename Params, typename Keyword>
341 : inline typename enable_if_c<has_param<Params,Keyword>::value,void>::type
342 18542 : opt_assign( T& target, Params const& p, Keyword k )
343 : {
344 : using namespace unit_test;
345 :
346 18542 : assign_op( target, p[k], static_cast<int>(0) );
347 18542 : }
348 :
349 : // ************************************************************************** //
350 : // ************** opt_get ************** //
351 : // ************************************************************************** //
352 :
353 : template<typename T, typename Params, typename Keyword>
354 : inline T
355 28032 : opt_get( Params const& p, Keyword k, T default_val )
356 : {
357 28032 : opt_assign( default_val, p, k );
358 :
359 28032 : return default_val;
360 : }
361 :
362 : // ************************************************************************** //
363 : // ************** opt_get ************** //
364 : // ************************************************************************** //
365 :
366 : template<typename Params, typename NP>
367 : inline typename enable_if_c<!has_param<Params,keyword<typename NP::id> >::value,
368 : named_parameter_combine<NP,Params> >::type
369 6424 : opt_append( Params const& params, NP const& np )
370 : {
371 6424 : return (params,np);
372 : }
373 :
374 : //____________________________________________________________________________//
375 :
376 : template<typename Params, typename NP>
377 : inline typename enable_if_c<has_param<Params,keyword<typename NP::id> >::value,Params>::type
378 1168 : opt_append( Params const& params, NP const& )
379 : {
380 1168 : return params;
381 : }
382 :
383 : } // namespace nfp
384 : } // namespace boost
385 :
386 : #include <boost/test/detail/enable_warnings.hpp>
387 :
388 : #endif // BOOST_TEST_UTILS_NAMED_PARAM
|