1 //-----------------------------------------------------------------------------
2 // boost-libs variant/libs/test/jobs.h header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
5 //
6 // Copyright (c) 2003
7 // Eric Friedman, Itay Maman
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12 
13 #ifndef _JOBSH_INC_
14 #define _JOBSH_INC_
15 
16 #include <algorithm>
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include <typeinfo>
21 #include <vector>
22 
23 #include "boost/variant/variant_fwd.hpp"
24 #include "boost/variant/get.hpp"
25 #include "boost/variant/apply_visitor.hpp"
26 #include "boost/variant/static_visitor.hpp"
27 
28 #include "boost/type_index.hpp"
29 #include "boost/detail/workaround.hpp"
30 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551))
31 #    pragma warn -lvc
32 #endif
33 
34 struct to_text : boost::static_visitor<std::string>
35 {
36 private: // NO_FUNCTION_TEMPLATE_ORDERING workaround
37 
38     template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
to_text_implto_text39     std::string to_text_impl(
40           const boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) >& operand, long
41         ) const
42     {
43         std::ostringstream ost;
44         ost << "[V] " << boost::apply_visitor(to_text(), operand);
45 
46         return ost.str();
47     }
48 
49     template <typename Value>
to_text_implto_text50     std::string to_text_impl(const Value& operand, int) const
51     {
52         std::ostringstream ost;
53         ost << "[V] " << operand;
54 
55         return ost.str();
56     }
57 
58 public:
59 
60     template <typename T>
operatorto_text61     std::string operator()(const T& operand) const
62     {
63         return to_text_impl(operand, 1L);
64     }
65 
66 };
67 
68 struct total_sizeof : boost::static_visitor<int>
69 {
total_sizeoftotal_sizeof70    total_sizeof() : total_(0) { }
71 
72    template<class Value>
operatortotal_sizeof73    int operator()(const Value&) const
74    {
75       total_ += sizeof(Value);
76       return total_;
77    }
78 
resulttotal_sizeof79    int result() const
80    {
81       return total_;
82    }
83 
84    mutable int total_;
85 
86 }; // total_sizeof
87 
88 
89 
90 //Function object: sum_int
91 //Description: Compute total sum of a series of numbers, (when called successively)
92 //Use sizeof(T) if applied with a non-integral type
93 struct sum_int : boost::static_visitor<int>
94 {
95 
sum_intsum_int96    sum_int() : total_(0) { }
97 
98 
99    template<int n>
100    struct int_to_type
101    {
102       BOOST_STATIC_CONSTANT(int, value = n);
103    };
104 
105    //Integral type - add numerical value
106    template<typename T>
addsum_int107    void add(T t, int_to_type<true> ) const
108    {
109       total_ += t;
110    }
111 
112    //Other types - add sizeof<T>
113    template<typename T>
addsum_int114    void add(T& , int_to_type<false> ) const
115    {
116       total_ += sizeof(T);
117    }
118 
119    template<typename T>
operatorsum_int120    int operator()(const T& t) const
121    {
122       //Int_to_type is used to select the correct add() overload
123       add(t, int_to_type<boost::is_integral<T>::value>());
124       return total_;
125    }
126 
resultsum_int127    int result() const
128    {
129       return total_;
130    }
131 
132 private:
133    mutable int total_;
134 
135 }; //sum_int
136 
137 
138 
139 
140 
141 
142 //Function object: sum_double
143 //Description: Compute total sum of a series of numbers, (when called successively)
144 //Accpetable input types: float, double (Other types are silently ignored)
145 struct sum_double : boost::static_visitor<double>
146 {
147 
sum_doublesum_double148    sum_double() : total_(0) { }
149 
operatorsum_double150    void operator()(float value) const
151    {
152       total_ += value;
153    }
154 
operatorsum_double155    void operator()(double value) const
156    {
157       total_ += value;
158    }
159 
160    template<typename T>
operatorsum_double161    void operator()(const T&) const
162    {
163       //Do nothing
164    }
165 
resultsum_double166    double result() const
167    {
168       return total_;
169    }
170 
171 private:
172    mutable double total_;
173 
174 }; //sum_double
175 
176 
177 
178 struct int_printer : boost::static_visitor<std::string>
179 {
180 
prefix_s_int_printer181    int_printer(std::string prefix_s = "") : prefix_s_(prefix_s) { }
int_printerint_printer182    int_printer(const int_printer& other) : prefix_s_(other.prefix_s_)
183    {
184       ost_ << other.str();
185    }
186 
operatorint_printer187    std::string operator()(int x) const
188    {
189       ost_ << prefix_s_ << x;
190       return str();
191    }
192 
operatorint_printer193    std::string operator()(const std::vector<int>& x) const
194    {
195       ost_ << prefix_s_;
196 
197       //Use another Int_printer object for printing a list of all integers
198       int_printer job(",");
199       ost_ << std::for_each(x.begin(), x.end(), job).str();
200 
201       return str();
202    }
203 
strint_printer204    std::string str() const
205    {
206       return ost_.str();
207    }
208 
209 private:
210    std::string prefix_s_;
211    mutable std::ostringstream ost_;
212 };  //int_printer
213 
214 
215 struct int_adder : boost::static_visitor<>
216 {
217 
int_adderint_adder218    int_adder(int rhs) : rhs_(rhs) { }
219 
operatorint_adder220    result_type operator()(int& lhs) const
221    {
222       lhs += rhs_;
223    }
224 
225    template<typename T>
operatorint_adder226    result_type operator()(const T& ) const
227    {
228       //Do nothing
229    }
230 
231    int rhs_;
232 }; //int_adder
233 
234 
235 
236 template<typename T>
237 struct spec
238 {
239    typedef T result;
240 };
241 
242 template<typename VariantType, typename S>
243 inline void verify(VariantType& var, spec<S>, std::string str = "")
244 {
245    const VariantType& cvar = var;
246 
247    BOOST_TEST(boost::apply_visitor(total_sizeof(), cvar) == sizeof(S));
248    BOOST_TEST(cvar.type() == boost::typeindex::type_id<S>());
249 
250    //
251    // Check get<>()
252    //
253    BOOST_TEST(boost::get<S>(&var));
254    BOOST_TEST(boost::get<S>(&cvar));
255 
256    const S* ptr1 = 0;
257    const S* ptr2 = 0;
258    try
259    {
260       S& r = boost::get<S>(var);
261       ptr1 = &r;
262    }
catch(const boost::bad_get &)263    catch(const boost::bad_get& )
264    {
265       BOOST_ERROR( "get<S> failed unexpectedly" );
266    }
267 
268    try
269    {
270       const S& cr = boost::get<S>(cvar);
271       ptr2 = &cr;
272    }
catch(const boost::bad_get &)273    catch(const boost::bad_get& )
274    {
275       BOOST_ERROR( "get<S> const failed unexpectedly" );
276    }
277 
278    BOOST_TEST(ptr1 != 0 && ptr2 == ptr1);
279 
280    //
281    // Check string content
282    //
283    if(str.length() > 0)
284    {
285       std::string temp = boost::apply_visitor(to_text(), cvar);
286       std::cout << "temp = " << temp << ", str = " << str << std::endl;
287       BOOST_TEST(temp == str);
288    }
289 }
290 
291 
292 template<typename VariantType, typename S>
verify_not(VariantType & var,spec<S>)293 inline void verify_not(VariantType& var, spec<S>)
294 {
295    const VariantType& cvar = var;
296 
297    BOOST_TEST(cvar.type() != boost::typeindex::type_id<S>());
298 
299    //
300    // Check get<>()
301    //
302    BOOST_TEST(!boost::get<S>(&var));
303    BOOST_TEST(!boost::get<S>(&cvar));
304 
305    const S* ptr1 = 0;
306    const S* ptr2 = 0;
307    try
308    {
309       S& r = boost::get<S>(var); // should throw
310       BOOST_ERROR( "get<S> passed unexpectedly" );
311 
312       ptr1 = &r;
313    }
314    catch(const boost::bad_get& )
315    {
316       // do nothing except pass-through
317    }
318 
319    try
320    {
321       const S& cr = boost::get<S>(var); // should throw
322       BOOST_ERROR( "get<S> const passed unexpectedly" );
323 
324       ptr2 = &cr;
325    }
326    catch(const boost::bad_get& )
327    {
328       // do nothing except pass-through
329    }
330 
331    BOOST_TEST(ptr1 == 0 && ptr2 == 0);
332 }
333 
334 
335 #endif //_JOBSH_INC_
336