1 //  (C) Copyright Gennadiy Rozental 2005.
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: named_params.hpp,v $
9 //
10 //  Version     : $Revision: 1.1.1.1 $
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 //____________________________________________________________________________//
27 
28 namespace boost {
29 
30 namespace nfp { // named function parameters
31 
32 // ************************************************************************** //
33 // **************              forward declarations            ************** //
34 // ************************************************************************** //
35 
36 template<typename T, typename unique_id,typename RefType>   struct named_parameter;
37 template<typename unique_id,bool required>                  struct keyword;
38 
39 namespace nfp_detail {
40 
41 template<typename NP1,typename NP2>        struct named_parameter_combine;
42 
43 // ************************************************************************** //
44 // **************          access_to_invalid_parameter         ************** //
45 // ************************************************************************** //
46 
47 struct access_to_invalid_parameter {};
48 
49 //____________________________________________________________________________//
50 
51 inline void
report_access_to_invalid_parameter()52 report_access_to_invalid_parameter()
53 {
54     throw access_to_invalid_parameter();
55 }
56 
57 //____________________________________________________________________________//
58 
59 // ************************************************************************** //
60 // **************                       nil                    ************** //
61 // ************************************************************************** //
62 
63 struct nil {
64     template<typename T>
operator Tboost::nfp::nfp_detail::nil65     operator T() const
66     { report_access_to_invalid_parameter(); static T* v = 0; return *v; }
67 
68     template<typename Arg1>
operator ()boost::nfp::nfp_detail::nil69     nil operator()( Arg1 const& )
70     { report_access_to_invalid_parameter(); return nil(); }
71 
72     template<typename Arg1,typename Arg2>
operator ()boost::nfp::nfp_detail::nil73     nil operator()( Arg1 const&, Arg2 const& )
74     { report_access_to_invalid_parameter(); return nil(); }
75 
76     template<typename Arg1,typename Arg2,typename Arg3>
operator ()boost::nfp::nfp_detail::nil77     nil operator()( Arg1 const&, Arg2 const&, Arg3 const& )
78     { report_access_to_invalid_parameter(); return nil(); }
79 
80     // Visitation support
81     template<typename Visitor>
apply_toboost::nfp::nfp_detail::nil82     void            apply_to( Visitor& V ) const {}
83 };
84 
85 // ************************************************************************** //
86 // **************              named_parameter_base            ************** //
87 // ************************************************************************** //
88 
89 template<typename Derived>
90 struct named_parameter_base {
91     template<typename NP>
92     named_parameter_combine<NP,Derived>
operator ,boost::nfp::nfp_detail::named_parameter_base93     operator,( NP const& np ) const { return named_parameter_combine<NP,Derived>( np, *static_cast<Derived const*>(this) ); }
94 };
95 
96 //____________________________________________________________________________//
97 
98 #if BOOST_WORKAROUND( __SUNPRO_CC, == 0x530 )
99 
100 struct unknown_id_helper {
101     template<typename UnknownId>
operator []boost::nfp::nfp_detail::unknown_id_helper102     nil     operator[]( keyword<UnknownId,false> kw ) const { return nil(); }
103 
104     template<typename UnknownId>
hasboost::nfp::nfp_detail::unknown_id_helper105     bool    has( keyword<UnknownId,false> ) const           { return false; }
106 };
107 
108 #endif
109 
110 //____________________________________________________________________________//
111 
112 // ************************************************************************** //
113 // **************             named_parameter_combine          ************** //
114 // ************************************************************************** //
115 
116 template<typename NP, typename Rest = nil>
117 struct named_parameter_combine : Rest, named_parameter_base<named_parameter_combine<NP,Rest> > {
118     typedef typename NP::ref_type  res_type;
119     typedef named_parameter_combine<NP,Rest> self_type;
120 
121     // Constructor
named_parameter_combineboost::nfp::nfp_detail::named_parameter_combine122     named_parameter_combine( NP const& np, Rest const& r )
123     : Rest( r ), m_param( np ) {}
124 
125     // Access methods
operator []boost::nfp::nfp_detail::named_parameter_combine126     res_type    operator[]( keyword<typename NP::id,true> kw ) const    { return m_param[kw]; }
operator []boost::nfp::nfp_detail::named_parameter_combine127     res_type    operator[]( keyword<typename NP::id,false> kw ) const   { return m_param[kw]; }
128     using       Rest::operator[];
129 
hasboost::nfp::nfp_detail::named_parameter_combine130     bool        has( keyword<typename NP::id,false> ) const             { return true; }
131     using       Rest::has;
132 
133     #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
134     template<typename NP>
operator ,boost::nfp::nfp_detail::named_parameter_combine135     named_parameter_combine<NP,self_type> operator,( NP const& np ) const
136     { return named_parameter_combine<NP,self_type>( np, *this ); }
137     #else
138     using       named_parameter_base<named_parameter_combine<NP,Rest> >::operator,;
139     #endif
140 
141     // Visitation support
142     template<typename Visitor>
apply_toboost::nfp::nfp_detail::named_parameter_combine143     void            apply_to( Visitor& V ) const
144     {
145         m_param.apply_to( V );
146 
147         Rest::apply_to( V );
148     }
149 private:
150     // Data members
151     NP          m_param;
152 };
153 
154 } // namespace nfp_detail
155 
156 // ************************************************************************** //
157 // **************             named_parameter_combine          ************** //
158 // ************************************************************************** //
159 
160 template<typename T, typename unique_id,typename ReferenceType=T&>
161 struct named_parameter
162 : nfp_detail::named_parameter_base<named_parameter<T, unique_id,ReferenceType> >
163 #if BOOST_WORKAROUND( __SUNPRO_CC, == 0x530 )
164 , nfp_detail::unknown_id_helper
165 #endif
166 {
167     typedef T               data_type;
168     typedef ReferenceType   ref_type;
169     typedef unique_id       id;
170 
171     // Constructor
named_parameterboost::nfp::named_parameter172     explicit        named_parameter( ref_type v ) : m_value( v ) {}
173 
174     // Access methods
operator []boost::nfp::named_parameter175     ref_type        operator[]( keyword<unique_id,true> ) const     { return m_value; }
operator []boost::nfp::named_parameter176     ref_type        operator[]( keyword<unique_id,false> ) const    { return m_value; }
177 #if BOOST_WORKAROUND( __SUNPRO_CC, == 0x530 )
178     using           nfp_detail::unknown_id_helper::operator[];
179 #else
180     template<typename UnknownId>
operator []boost::nfp::named_parameter181     nfp_detail::nil  operator[]( keyword<UnknownId,false> ) const   { return nfp_detail::nil(); }
182 #endif
183 
hasboost::nfp::named_parameter184     bool            has( keyword<unique_id,false> ) const           { return true; }
185 #if BOOST_WORKAROUND( __SUNPRO_CC, == 0x530 )
186     using           nfp_detail::unknown_id_helper::has;
187 #else
188     template<typename UnknownId>
hasboost::nfp::named_parameter189     bool            has( keyword<UnknownId,false> ) const           { return false; }
190 #endif
191 
192     // Visitation support
193     template<typename Visitor>
apply_toboost::nfp::named_parameter194     void            apply_to( Visitor& V ) const
195     {
196         V.set_parameter( rtti::type_id<unique_id>(), m_value );
197     }
198 
199 private:
200     // Data members
201     ref_type        m_value;
202 };
203 
204 //____________________________________________________________________________//
205 
206 // ************************************************************************** //
207 // **************                    no_params                 ************** //
208 // ************************************************************************** //
209 
210 namespace nfp_detail {
211 typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
212 }
213 
214 namespace {
215 nfp_detail::no_params_type no_params( '\0' );
216 } // local namespace
217 
218 //____________________________________________________________________________//
219 
220 // ************************************************************************** //
221 // **************                     keyword                  ************** //
222 // ************************************************************************** //
223 
224 template<typename unique_id, bool required = false>
225 struct keyword {
226     typedef unique_id id;
227 
228     template<typename T>
229     named_parameter<T const,unique_id>
operator =boost::nfp::keyword230     operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }
231 
232     template<typename T>
233     named_parameter<T,unique_id>
operator =boost::nfp::keyword234     operator=( T& t ) const   { return named_parameter<T,unique_id>( t ); }
235 
236     named_parameter<char const*,unique_id,char const*>
operator =boost::nfp::keyword237     operator=( char const* t ) const   { return named_parameter<char const*,unique_id,char const*>( t ); }
238 };
239 
240 //____________________________________________________________________________//
241 
242 // ************************************************************************** //
243 // **************                  typed_keyword               ************** //
244 // ************************************************************************** //
245 
246 template<typename T, typename unique_id, bool required = false>
247 struct typed_keyword : keyword<unique_id,required> {
248     named_parameter<T const,unique_id>
operator =boost::nfp::typed_keyword249     operator=( T const& t ) const       { return named_parameter<T const,unique_id>( t ); }
250 
251     named_parameter<T,unique_id>
operator =boost::nfp::typed_keyword252     operator=( T& t ) const             { return named_parameter<T,unique_id>( t ); }
253 };
254 
255 //____________________________________________________________________________//
256 
257 template<typename unique_id>
258 struct typed_keyword<bool,unique_id,false>
259 : keyword<unique_id,false>
260 , named_parameter<bool,unique_id,bool> {
261     typedef unique_id id;
262 
typed_keywordboost::nfp::typed_keyword263     typed_keyword() : named_parameter<bool,unique_id,bool>( true ) {}
264 
265     named_parameter<bool,unique_id,bool>
operator !boost::nfp::typed_keyword266     operator!() const           { return named_parameter<bool,unique_id,bool>( false ); }
267 };
268 
269 //____________________________________________________________________________//
270 
271 // ************************************************************************** //
272 // **************                optionally_assign             ************** //
273 // ************************************************************************** //
274 
275 template<typename T>
276 inline void
optionally_assign(T &,nfp_detail::nil)277 optionally_assign( T&, nfp_detail::nil )
278 {
279     nfp_detail::report_access_to_invalid_parameter();
280 }
281 
282 //____________________________________________________________________________//
283 
284 template<typename T, typename Source>
285 inline void
286 #if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \
287     || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) )
optionally_assign(T & target,Source src)288 optionally_assign( T& target, Source src )
289 #else
290 optionally_assign( T& target, Source const& src )
291 #endif
292 {
293     using namespace unit_test;
294 
295     assign_op( target, src, 0 );
296 }
297 
298 //____________________________________________________________________________//
299 
300 template<typename T, typename Params, typename Keyword>
301 inline void
optionally_assign(T & target,Params const & p,Keyword k)302 optionally_assign( T& target, Params const& p, Keyword k )
303 {
304     if( p.has(k) )
305         optionally_assign( target, p[k] );
306 }
307 
308 //____________________________________________________________________________//
309 
310 } // namespace nfp
311 
312 } // namespace boost
313 
314 // ***************************************************************************
315 //   Revision History:
316 //
317 //  $Log: named_params.hpp,v $
318 //  Revision 1.1.1.1  2006/03/20 20:15:28  ewalkup
319 //  boost libraries
320 //
321 //  Revision 1.4  2005/06/13 10:35:08  schoepflin
322 //  Enable optionally_assign() overload workaround for Tru64/CXX-6.5 as well.
323 //
324 //  Revision 1.3  2005/06/05 18:10:59  grafik
325 //  named_param.hpp; Work around CW not handling operator, using declaration, by using a real operator,().
326 //  token_iterator_test.cpp; Work around CW-8 confused with array initialization.
327 //
328 //  Revision 1.2  2005/05/03 05:02:49  rogeeff
329 //  como fixes
330 //
331 //  Revision 1.1  2005/04/12 06:48:12  rogeeff
332 //  Runtime.Param library initial commit
333 //
334 // ***************************************************************************
335 
336 #endif // BOOST_TEST_NAMED_PARAM_022505GER
337 
338