blob: 371d5945a8daac4b38e9bc5eefc30f5fe39d2912 [file] [log] [blame]
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001// (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 <ndnboost/config.hpp>
20#include <ndnboost/detail/workaround.hpp>
21
22// Boost.Test
23#include <ndnboost/test/utils/rtti.hpp>
24#include <ndnboost/test/utils/assign_op.hpp>
25
26#include <ndnboost/type_traits/remove_reference.hpp>
27
28#include <ndnboost/test/detail/suppress_warnings.hpp>
29
30//____________________________________________________________________________//
31
32namespace ndnboost {
33
34namespace nfp { // named function parameters
35
36// ************************************************************************** //
37// ************** forward declarations ************** //
38// ************************************************************************** //
39
40template<typename T, typename unique_id,typename RefType> struct named_parameter;
41template<typename unique_id,bool required> struct keyword;
42
43namespace nfp_detail {
44
45template<typename NP1,typename NP2> struct named_parameter_combine;
46
47// ************************************************************************** //
48// ************** access_to_invalid_parameter ************** //
49// ************************************************************************** //
50
51struct access_to_invalid_parameter {};
52
53//____________________________________________________________________________//
54
55inline void
56report_access_to_invalid_parameter()
57{
58 throw access_to_invalid_parameter();
59}
60
61//____________________________________________________________________________//
62
63// ************************************************************************** //
64// ************** nil ************** //
65// ************************************************************************** //
66
67struct 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; }
97private:
98 nil() {}
99};
100
101// ************************************************************************** //
102// ************** named_parameter_base ************** //
103// ************************************************************************** //
104
105template<typename Derived>
106struct 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
118template<typename NP, typename Rest = nil>
119struct 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 }
159private:
160 // Data members
161 NP m_param;
162};
163
164} // namespace nfp_detail
165
166// ************************************************************************** //
167// ************** named_parameter ************** //
168// ************************************************************************** //
169
170template<typename T, typename unique_id,typename ReferenceType=T&>
171struct 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
210private:
211 // Data members
212 ref_type m_value;
213 mutable bool m_erased;
214};
215
216//____________________________________________________________________________//
217
218// ************************************************************************** //
219// ************** no_params ************** //
220// ************************************************************************** //
221
222namespace nfp_detail {
223typedef named_parameter<char, struct no_params_type_t,char> no_params_type;
224} // namespace nfp_detail
225
226namespace {
227nfp_detail::no_params_type no_params( '\0' );
228} // local namespace
229
230//____________________________________________________________________________//
231
232// ************************************************************************** //
233// ************** keyword ************** //
234// ************************************************************************** //
235
236template<typename unique_id, bool required = false>
237struct 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
258template<typename T, typename unique_id, bool required = false>
259struct 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
269template<typename unique_id>
270struct 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
287template<typename T>
288inline void
289optionally_assign( T&, nfp_detail::nil )
290{
291 nfp_detail::report_access_to_invalid_parameter();
292}
293
294//____________________________________________________________________________//
295
296template<typename T, typename Source>
297inline void
298#if BOOST_WORKAROUND( __MWERKS__, BOOST_TESTED_AT( 0x3003 ) ) \
299 || BOOST_WORKAROUND( __DECCXX_VER, BOOST_TESTED_AT(60590042) )
300optionally_assign( T& target, Source src )
301#else
302optionally_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
312template<typename T, typename Params, typename Keyword>
313inline void
314optionally_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 ndnboost
325
326#include <ndnboost/test/detail/enable_warnings.hpp>
327
328#endif // BOOST_TEST_NAMED_PARAM_022505GER
329