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
report_access_to_invalid_parameter()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)
operator Tboost::nfp::nfp_detail::nil70     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>
any_castboost::nfp::nfp_detail::nil77     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>
operator ()boost::nfp::nfp_detail::nil81     nil operator()( Arg1 const& )
82     { report_access_to_invalid_parameter(); return nil(); }
83 
84     template<typename Arg1,typename Arg2>
operator ()boost::nfp::nfp_detail::nil85     nil operator()( Arg1 const&, Arg2 const& )
86     { report_access_to_invalid_parameter(); return nil(); }
87 
88     template<typename Arg1,typename Arg2,typename Arg3>
operator ()boost::nfp::nfp_detail::nil89     nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
90     { report_access_to_invalid_parameter(); return nil(); }
91 
92     // Visitation support
93     template<typename Visitor>
apply_toboost::nfp::nfp_detail::nil94     void            apply_to( Visitor& V ) const {}
95 
instboost::nfp::nfp_detail::nil96     static nil&     inst() { static nil s_inst; return s_inst; }
97 private:
nilboost::nfp::nfp_detail::nil98     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>
operator ,boost::nfp::nfp_detail::named_parameter_base109     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
named_parameter_combineboost::nfp::nfp_detail::named_parameter_combine126     named_parameter_combine( NP const& np, Rest const& r )
127     : Rest( r )
128     , m_param( np )
129     {}
130 
131     // Access methods
operator []boost::nfp::nfp_detail::named_parameter_combine132     res_type    operator[]( keyword<typename NP::id,true> kw ) const    { return m_param[kw]; }
operator []boost::nfp::nfp_detail::named_parameter_combine133     res_type    operator[]( keyword<typename NP::id,false> kw ) const   { return m_param[kw]; }
134     using       Rest::operator[];
135 
hasboost::nfp::nfp_detail::named_parameter_combine136     bool        has( keyword<typename NP::id,false> kw ) const          { return m_param.has( kw ); }
137     using       Rest::has;
138 
eraseboost::nfp::nfp_detail::named_parameter_combine139     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>
operator ,boost::nfp::nfp_detail::named_parameter_combine145     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>
apply_toboost::nfp::nfp_detail::named_parameter_combine153     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
named_parameterboost::nfp::named_parameter180     explicit        named_parameter( ref_type v )
181     : m_value( v )
182     , m_erased( false )
183     {}
named_parameterboost::nfp::named_parameter184     named_parameter( named_parameter const& np )
185     : m_value( np.m_value )
186     , m_erased( np.m_erased )
187     {}
188 
189     // Access methods
operator []boost::nfp::named_parameter190     ref_type        operator[]( keyword<unique_id,true> ) const     { return m_erased ? nil_t::inst().template any_cast<ref_type>() :  m_value; }
operator []boost::nfp::named_parameter191     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>
operator []boost::nfp::named_parameter193     nil_t           operator[]( keyword<UnknownId,false> ) const    { return nil_t::inst(); }
194 
hasboost::nfp::named_parameter195     bool            has( keyword<unique_id,false> ) const           { return !m_erased; }
196     template<typename UnknownId>
hasboost::nfp::named_parameter197     bool            has( keyword<UnknownId,false> ) const           { return false; }
198 
eraseboost::nfp::named_parameter199     void            erase( keyword<unique_id,false> ) const         { m_erased = true; }
200     template<typename UnknownId>
eraseboost::nfp::named_parameter201     void            erase( keyword<UnknownId,false> ) const         {}
202 
203     // Visitation support
204     template<typename Visitor>
apply_toboost::nfp::named_parameter205     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>
operator =boost::nfp::keyword242     operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }
243 
244     template<typename T>
245     named_parameter<T,unique_id>
operator =boost::nfp::keyword246     operator=( T& t ) const   { return named_parameter<T,unique_id>( t ); }
247 
248     named_parameter<char const*,unique_id,char const*>
operator =boost::nfp::keyword249     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>
operator =boost::nfp::typed_keyword261     operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }
262 
263     named_parameter<T,unique_id>
operator =boost::nfp::typed_keyword264     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 
typed_keywordboost::nfp::typed_keyword275     typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
276 
277     named_parameter<bool,unique_id,bool>
operator !boost::nfp::typed_keyword278     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
optionally_assign(T &,nfp_detail::nil)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) )
optionally_assign(T & target,Source src)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
optionally_assign(T & target,Params const & p,Keyword k)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