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)
6 // See http://www.boost.org/libs/test for the library home page.
10 // Version : $Revision$
12 // Description : named function parameters library
13 // ***************************************************************************
15 #ifndef BOOST_TEST_UTILS_NAMED_PARAM
16 #define BOOST_TEST_UTILS_NAMED_PARAM
19 #include <boost/config.hpp>
20 #include <boost/detail/workaround.hpp>
23 #include <boost/test/utils/rtti.hpp>
24 #include <boost/test/utils/assign_op.hpp>
26 #include <boost/type_traits/remove_reference.hpp>
27 #include <boost/type_traits/remove_cv.hpp>
29 #include <boost/test/detail/throw_exception.hpp>
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>
39 #include <boost/test/detail/suppress_warnings.hpp>
41 //____________________________________________________________________________//
44 namespace nfp { // named function parameters
46 // ************************************************************************** //
47 // ************** forward declarations ************** //
48 // ************************************************************************** //
50 template<typename unique_id, bool required> struct keyword;
51 template<typename T, typename unique_id, bool required = false> struct typed_keyword;
53 template<typename T, typename unique_id, typename RefType=T&> struct named_parameter;
54 template<typename NP1,typename NP2> struct named_parameter_combine;
56 // ************************************************************************** //
57 // ************** is_named_param_pack ************** //
58 // ************************************************************************** //
60 /// is_named_param_pack<T>::value is true if T is parameters pack
63 struct is_named_param_pack : public mpl::false_ {};
65 template<typename T, typename unique_id, typename RefType>
66 struct is_named_param_pack<named_parameter<T,unique_id,RefType> > : public mpl::true_ {};
68 template<typename NP, typename Rest>
69 struct is_named_param_pack<named_parameter_combine<NP,Rest> > : public mpl::true_ {};
71 // ************************************************************************** //
72 // ************** param_type ************** //
73 // ************************************************************************** //
75 /// param_type<Params,Keyword,Default>::type is the type of the parameter
76 /// corresponding to the Keyword (if parameter is present) or Default
78 template<typename NP, typename Keyword, typename DefaultType=void>
80 : mpl::if_<typename is_same<typename NP::id,typename Keyword::id>::type,
81 typename remove_cv<typename NP::data_type>::type,
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> {};
90 // ************************************************************************** //
91 // ************** has_param ************** //
92 // ************************************************************************** //
94 /// has_param<Params,Keyword>::value is true if Params has parameter corresponding
97 template<typename NP, typename Keyword>
98 struct has_param : is_same<typename NP::id,typename Keyword::id> {};
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> {};
105 // ************************************************************************** //
106 // ************** access_to_invalid_parameter ************** //
107 // ************************************************************************** //
109 namespace nfp_detail {
111 struct access_to_invalid_parameter {};
113 //____________________________________________________________________________//
116 report_access_to_invalid_parameter( bool v )
118 BOOST_TEST_I_ASSRT( !v, access_to_invalid_parameter() );
121 } // namespace nfp_detail
123 // ************************************************************************** //
124 // ************** nil ************** //
125 // ************************************************************************** //
129 #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC) || defined(BOOST_EMBTC)
132 operator T const&() const
134 { nfp_detail::report_access_to_invalid_parameter(true); static T* v = 0; return *v; }
138 { nfp_detail::report_access_to_invalid_parameter(true); static typename remove_reference<T>::type* v = 0; return *v; }
140 template<typename Arg1>
141 nil operator()( Arg1 const& )
142 { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
144 template<typename Arg1,typename Arg2>
145 nil operator()( Arg1 const&, Arg2 const& )
146 { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
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(); }
152 // Visitation support
153 template<typename Visitor>
154 void apply_to( Visitor& /*v*/ ) const {}
156 static nil& inst() { static nil s_inst; return s_inst; }
161 // ************************************************************************** //
162 // ************** named_parameter_base ************** //
163 // ************************************************************************** //
165 namespace nfp_detail {
167 template<typename Derived>
168 struct named_parameter_base {
169 template<typename NP>
170 named_parameter_combine<NP,Derived>
171 operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
174 } // namespace nfp_detail
176 // ************************************************************************** //
177 // ************** named_parameter_combine ************** //
178 // ************************************************************************** //
180 template<typename NP, typename Rest = nil>
181 struct named_parameter_combine
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;
188 named_parameter_combine( NP const& np, Rest const& r )
195 res_type operator[]( keyword<typename NP::id,true> kw ) const { return m_param[kw]; }
196 res_type operator[]( keyword<typename NP::id,false> kw ) const { return m_param[kw]; }
197 using Rest::operator[];
199 bool has( keyword<typename NP::id,false> kw ) const { return m_param.has( kw ); }
202 void erase( keyword<typename NP::id,false> kw ) const { m_param.erase( kw ); }
205 using nfp_detail::named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
207 // Visitation support
208 template<typename Visitor>
209 void apply_to( Visitor& V ) const
211 m_param.apply_to( V );
220 // ************************************************************************** //
221 // ************** named_parameter ************** //
222 // ************************************************************************** //
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> >
229 typedef RefType ref_type;
230 typedef unique_id id;
233 explicit named_parameter( ref_type v )
237 named_parameter( named_parameter const& np )
238 : m_value( np.m_value )
239 , m_erased( np.m_erased )
243 ref_type operator[]( keyword<unique_id,true> ) const { return m_erased ? nil::inst().template any_cast<ref_type>() : m_value; }
244 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(); }
248 bool has( keyword<unique_id,false> ) const { return !m_erased; }
249 template<typename UnknownId>
250 bool has( keyword<UnknownId,false> ) const { return false; }
252 void erase( keyword<unique_id,false> ) const { m_erased = true; }
253 template<typename UnknownId>
254 void erase( keyword<UnknownId,false> ) const {}
256 // Visitation support
257 template<typename Visitor>
258 void apply_to( Visitor& V ) const
260 V.set_parameter( rtti::type_id<unique_id>(), m_value );
266 mutable bool m_erased;
269 // ************************************************************************** //
270 // ************** no_params ************** //
271 // ************************************************************************** //
273 typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
276 no_params_type no_params( '\0' );
279 // ************************************************************************** //
280 // ************** keyword ************** //
281 // ************************************************************************** //
283 template<typename unique_id, bool required = false>
285 typedef unique_id id;
288 named_parameter<T const,unique_id>
289 operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
292 named_parameter<T,unique_id>
293 operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
295 named_parameter<char const*,unique_id,char const*>
296 operator=( char const* t ) const { return named_parameter<char const*,unique_id,char const*>( t ); }
299 //____________________________________________________________________________//
301 // ************************************************************************** //
302 // ************** typed_keyword ************** //
303 // ************************************************************************** //
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 operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
310 named_parameter<T,unique_id>
311 operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
314 //____________________________________________________________________________//
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;
322 typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
324 named_parameter<bool,unique_id,bool>
325 operator!() const { return named_parameter<bool,unique_id,bool>( false ); }
328 // ************************************************************************** //
329 // ************** opt_assign ************** //
330 // ************************************************************************** //
332 template<typename T, typename Params, typename Keyword>
333 inline typename enable_if_c<!has_param<Params,Keyword>::value,void>::type
334 opt_assign( T& /*target*/, Params const& /*p*/, Keyword /*k*/ )
338 //____________________________________________________________________________//
340 template<typename T, typename Params, typename Keyword>
341 inline typename enable_if_c<has_param<Params,Keyword>::value,void>::type
342 opt_assign( T& target, Params const& p, Keyword k )
344 using namespace unit_test;
346 assign_op( target, p[k], static_cast<int>(0) );
349 // ************************************************************************** //
350 // ************** opt_get ************** //
351 // ************************************************************************** //
353 template<typename T, typename Params, typename Keyword>
355 opt_get( Params const& p, Keyword k, T default_val )
357 opt_assign( default_val, p, k );
362 // ************************************************************************** //
363 // ************** opt_get ************** //
364 // ************************************************************************** //
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 opt_append( Params const& params, NP const& np )
374 //____________________________________________________________________________//
376 template<typename Params, typename NP>
377 inline typename enable_if_c<has_param<Params,keyword<typename NP::id> >::value,Params>::type
378 opt_append( Params const& params, NP const& )
386 #include <boost/test/detail/enable_warnings.hpp>
388 #endif // BOOST_TEST_UTILS_NAMED_PARAM