File indexing completed on 2025-01-18 09:52:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_TEST_UTILS_NAMED_PARAM
0016 #define BOOST_TEST_UTILS_NAMED_PARAM
0017
0018
0019 #include <boost/config.hpp>
0020 #include <boost/detail/workaround.hpp>
0021
0022
0023 #include <boost/test/utils/rtti.hpp>
0024 #include <boost/test/utils/assign_op.hpp>
0025
0026 #include <boost/type_traits/remove_reference.hpp>
0027 #include <boost/type_traits/remove_cv.hpp>
0028
0029 #include <boost/test/detail/throw_exception.hpp>
0030
0031
0032 #include <boost/mpl/if.hpp>
0033 #include <boost/mpl/or.hpp>
0034 #include <boost/type_traits/is_same.hpp>
0035 #include <boost/type_traits/remove_cv.hpp>
0036 #include <boost/utility/enable_if.hpp>
0037 #include <boost/mpl/bool.hpp>
0038
0039 #include <boost/test/detail/suppress_warnings.hpp>
0040
0041
0042
0043 namespace boost {
0044 namespace nfp {
0045
0046
0047
0048
0049
0050 template<typename unique_id, bool required> struct keyword;
0051 template<typename T, typename unique_id, bool required = false> struct typed_keyword;
0052
0053 template<typename T, typename unique_id, typename RefType=T&> struct named_parameter;
0054 template<typename NP1,typename NP2> struct named_parameter_combine;
0055
0056
0057
0058
0059
0060
0061
0062 template<typename T>
0063 struct is_named_param_pack : public mpl::false_ {};
0064
0065 template<typename T, typename unique_id, typename RefType>
0066 struct is_named_param_pack<named_parameter<T,unique_id,RefType> > : public mpl::true_ {};
0067
0068 template<typename NP, typename Rest>
0069 struct is_named_param_pack<named_parameter_combine<NP,Rest> > : public mpl::true_ {};
0070
0071
0072
0073
0074
0075
0076
0077
0078 template<typename NP, typename Keyword, typename DefaultType=void>
0079 struct param_type
0080 : mpl::if_<typename is_same<typename NP::id,typename Keyword::id>::type,
0081 typename remove_cv<typename NP::data_type>::type,
0082 DefaultType> {};
0083
0084 template<typename NP, typename Rest, typename Keyword, typename DefaultType>
0085 struct param_type<named_parameter_combine<NP,Rest>,Keyword,DefaultType>
0086 : mpl::if_<typename is_same<typename NP::id,typename Keyword::id>::type,
0087 typename remove_cv<typename NP::data_type>::type,
0088 typename param_type<Rest,Keyword,DefaultType>::type> {};
0089
0090
0091
0092
0093
0094
0095
0096
0097 template<typename NP, typename Keyword>
0098 struct has_param : is_same<typename NP::id,typename Keyword::id> {};
0099
0100 template<typename NP, typename Rest, typename Keyword>
0101 struct has_param<named_parameter_combine<NP,Rest>,Keyword>
0102 : mpl::or_<typename is_same<typename NP::id,typename Keyword::id>::type,
0103 typename has_param<Rest,Keyword>::type> {};
0104
0105
0106
0107
0108
0109 namespace nfp_detail {
0110
0111 struct access_to_invalid_parameter {};
0112
0113
0114
0115 inline void
0116 report_access_to_invalid_parameter( bool v )
0117 {
0118 BOOST_TEST_I_ASSRT( !v, access_to_invalid_parameter() );
0119 }
0120
0121 }
0122
0123
0124
0125
0126
0127 struct nil {
0128 template<typename T>
0129 #if defined(__GNUC__) || defined(__HP_aCC) || defined(__EDG__) || defined(__SUNPRO_CC) || defined(BOOST_EMBTC)
0130 operator T() const
0131 #else
0132 operator T const&() const
0133 #endif
0134 { nfp_detail::report_access_to_invalid_parameter(true); static T* v = 0; return *v; }
0135
0136 template<typename T>
0137 T any_cast() const
0138 { nfp_detail::report_access_to_invalid_parameter(true); static typename remove_reference<T>::type* v = 0; return *v; }
0139
0140 template<typename Arg1>
0141 nil operator()( Arg1 const& )
0142 { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
0143
0144 template<typename Arg1,typename Arg2>
0145 nil operator()( Arg1 const&, Arg2 const& )
0146 { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
0147
0148 template<typename Arg1,typename Arg2,typename Arg3>
0149 nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
0150 { nfp_detail::report_access_to_invalid_parameter(true); return nil(); }
0151
0152
0153 template<typename Visitor>
0154 void apply_to( Visitor& ) const {}
0155
0156 static nil& inst() { static nil s_inst; return s_inst; }
0157 private:
0158 nil() {}
0159 };
0160
0161
0162
0163
0164
0165 namespace nfp_detail {
0166
0167 template<typename Derived>
0168 struct named_parameter_base {
0169 template<typename NP>
0170 named_parameter_combine<NP,Derived>
0171 operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
0172 };
0173
0174 }
0175
0176
0177
0178
0179
0180 template<typename NP, typename Rest = nil>
0181 struct named_parameter_combine
0182 : Rest
0183 , nfp_detail::named_parameter_base<named_parameter_combine<NP,Rest> > {
0184 typedef typename NP::ref_type res_type;
0185 typedef named_parameter_combine<NP,Rest> self_type;
0186
0187
0188 named_parameter_combine( NP const& np, Rest const& r )
0189 : Rest( r )
0190 , m_param( np )
0191 {
0192 }
0193
0194
0195 res_type operator[]( keyword<typename NP::id,true> kw ) const { return m_param[kw]; }
0196 res_type operator[]( keyword<typename NP::id,false> kw ) const { return m_param[kw]; }
0197 using Rest::operator[];
0198
0199 bool has( keyword<typename NP::id,false> kw ) const { return m_param.has( kw ); }
0200 using Rest::has;
0201
0202 void erase( keyword<typename NP::id,false> kw ) const { m_param.erase( kw ); }
0203 using Rest::erase;
0204
0205 using nfp_detail::named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
0206
0207
0208 template<typename Visitor>
0209 void apply_to( Visitor& V ) const
0210 {
0211 m_param.apply_to( V );
0212
0213 Rest::apply_to( V );
0214 }
0215 private:
0216
0217 NP m_param;
0218 };
0219
0220
0221
0222
0223
0224 template<typename T, typename unique_id, typename RefType>
0225 struct named_parameter
0226 : nfp_detail::named_parameter_base<named_parameter<T,unique_id,RefType> >
0227 {
0228 typedef T data_type;
0229 typedef RefType ref_type;
0230 typedef unique_id id;
0231
0232
0233 explicit named_parameter( ref_type v )
0234 : m_value( v )
0235 , m_erased( false )
0236 {}
0237 named_parameter( named_parameter const& np )
0238 : m_value( np.m_value )
0239 , m_erased( np.m_erased )
0240 {}
0241
0242
0243 ref_type operator[]( keyword<unique_id,true> ) const { return m_erased ? nil::inst().template any_cast<ref_type>() : m_value; }
0244 ref_type operator[]( keyword<unique_id,false> ) const { return m_erased ? nil::inst().template any_cast<ref_type>() : m_value; }
0245 template<typename UnknownId>
0246 nil operator[]( keyword<UnknownId,false> ) const { return nil::inst(); }
0247
0248 bool has( keyword<unique_id,false> ) const { return !m_erased; }
0249 template<typename UnknownId>
0250 bool has( keyword<UnknownId,false> ) const { return false; }
0251
0252 void erase( keyword<unique_id,false> ) const { m_erased = true; }
0253 template<typename UnknownId>
0254 void erase( keyword<UnknownId,false> ) const {}
0255
0256
0257 template<typename Visitor>
0258 void apply_to( Visitor& V ) const
0259 {
0260 V.set_parameter( rtti::type_id<unique_id>(), m_value );
0261 }
0262
0263 private:
0264
0265 ref_type m_value;
0266 mutable bool m_erased;
0267 };
0268
0269
0270
0271
0272
0273 typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
0274
0275 namespace {
0276 no_params_type no_params( '\0' );
0277 }
0278
0279
0280
0281
0282
0283 template<typename unique_id, bool required = false>
0284 struct keyword {
0285 typedef unique_id id;
0286
0287 template<typename T>
0288 named_parameter<T const,unique_id>
0289 operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
0290
0291 template<typename T>
0292 named_parameter<T,unique_id>
0293 operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
0294
0295 named_parameter<char const*,unique_id,char const*>
0296 operator=( char const* t ) const { return named_parameter<char const*,unique_id,char const*>( t ); }
0297 };
0298
0299
0300
0301
0302
0303
0304
0305 template<typename T, typename unique_id, bool required>
0306 struct typed_keyword : keyword<unique_id,required> {
0307 named_parameter<T const,unique_id>
0308 operator=( T const& t ) const { return named_parameter<T const,unique_id>( t ); }
0309
0310 named_parameter<T,unique_id>
0311 operator=( T& t ) const { return named_parameter<T,unique_id>( t ); }
0312 };
0313
0314
0315
0316 template<typename unique_id, bool required>
0317 struct typed_keyword<bool,unique_id,required>
0318 : keyword<unique_id,required>
0319 , named_parameter<bool,unique_id,bool> {
0320 typedef unique_id id;
0321
0322 typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
0323
0324 named_parameter<bool,unique_id,bool>
0325 operator!() const { return named_parameter<bool,unique_id,bool>( false ); }
0326 };
0327
0328
0329
0330
0331
0332 template<typename T, typename Params, typename Keyword>
0333 inline typename enable_if_c<!has_param<Params,Keyword>::value,void>::type
0334 opt_assign( T& , Params const& , Keyword )
0335 {
0336 }
0337
0338
0339
0340 template<typename T, typename Params, typename Keyword>
0341 inline typename enable_if_c<has_param<Params,Keyword>::value,void>::type
0342 opt_assign( T& target, Params const& p, Keyword k )
0343 {
0344 using namespace unit_test;
0345
0346 assign_op( target, p[k], static_cast<int>(0) );
0347 }
0348
0349
0350
0351
0352
0353 template<typename T, typename Params, typename Keyword>
0354 inline T
0355 opt_get( Params const& p, Keyword k, T default_val )
0356 {
0357 opt_assign( default_val, p, k );
0358
0359 return default_val;
0360 }
0361
0362
0363
0364
0365
0366 template<typename Params, typename NP>
0367 inline typename enable_if_c<!has_param<Params,keyword<typename NP::id> >::value,
0368 named_parameter_combine<NP,Params> >::type
0369 opt_append( Params const& params, NP const& np )
0370 {
0371 return (params,np);
0372 }
0373
0374
0375
0376 template<typename Params, typename NP>
0377 inline typename enable_if_c<has_param<Params,keyword<typename NP::id> >::value,Params>::type
0378 opt_append( Params const& params, NP const& )
0379 {
0380 return params;
0381 }
0382
0383 }
0384 }
0385
0386 #include <boost/test/detail/enable_warnings.hpp>
0387
0388 #endif