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