• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Boost.Flyweight basic test template.
2  *
3  * Copyright 2006-2019 Joaquin M Lopez Munoz.
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * See http://www.boost.org/libs/flyweight for library home page.
9  */
10 
11 #ifndef BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
12 #define BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
13 
14 #if defined(_MSC_VER)
15 #pragma once
16 #endif
17 
18 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
19 #include <boost/detail/lightweight_test.hpp>
20 #include <boost/flyweight/key_value.hpp>
21 #include <boost/mpl/apply.hpp>
22 #include <boost/utility/value_init.hpp>
23 #include <string>
24 #include <sstream>
25 #include "heavy_objects.hpp"
26 
27 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
28 #include <utility>
29 #endif
30 
31 #if !defined(BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT)
32 #include <boost/functional/hash.hpp>
33 
34 #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
35 #include <functional>
36 #endif
37 #endif
38 
39 #define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
40 
41 template<typename Flyweight,typename ForwardIterator>
test_basic_template(ForwardIterator first,ForwardIterator last BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE (Flyweight))42 void test_basic_template(
43   ForwardIterator first,ForwardIterator last
44   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
45 {
46   typedef typename Flyweight::value_type value_type;
47 
48   ForwardIterator it;
49 
50   for(it=first;it!=last;++it){
51     /* construct/copy/destroy */
52 
53     Flyweight                            f1(*it);
54     Flyweight                            f2;
55     Flyweight                            c1(f1);
56     const Flyweight                      c2(static_cast<const Flyweight&>(f2));
57     value_type                           v1(*it);
58     boost::value_initialized<value_type> v2;
59     BOOST_TEST(f1.get_key()==*it);
60     BOOST_TEST((f1==f2)==(f1.get()==v2.data()));
61     BOOST_TEST(f1==c1);
62     BOOST_TEST(f2==c2);
63 
64 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
65     Flyweight cr1(std::move(c1));
66     Flyweight cr2(std::move(c2));
67     BOOST_TEST(f1==cr1);
68     BOOST_TEST(f2==cr2);
69 #endif
70 
71 #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
72     /* testcase for https://svn.boost.org/trac/boost/ticket/10439 */
73 
74     Flyweight f3={};
75     BOOST_TEST(f3==f2);
76 #endif
77 
78     f1=((void)0,f1); /* self assignment warning */
79     BOOST_TEST(f1==f1);
80 
81     c1=f2;
82     BOOST_TEST(c1==f2);
83 
84     c1=f1;
85     BOOST_TEST(c1==f1);
86 
87     /* convertibility to underlying type */
88 
89     BOOST_TEST(f1.get()==v1);
90 
91     /* identity of reference */
92 
93     BOOST_TEST(&f1.get()==&c1.get());
94 
95     /* modifiers */
96 
97     f1.swap(f1);
98     BOOST_TEST(f1==c1);
99 
100     f1.swap(f2);
101     BOOST_TEST(f1==c2);
102     BOOST_TEST(f2==c1);
103 
104     boost::flyweights::swap(f1,f2);
105     BOOST_TEST(f1==c1);
106     BOOST_TEST(f2==c2);
107 
108     /* specialized algorithms */
109 
110     std::ostringstream oss1;
111     oss1<<f1;
112     std::ostringstream oss2;
113     oss2<<f1.get();
114     BOOST_TEST(oss1.str()==oss2.str());
115 
116 #if !defined(BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT)
117 
118     /* hash support */
119 
120     BOOST_TEST(boost::hash<Flyweight>()(f1)==boost::hash<Flyweight>()(c1));
121     BOOST_TEST(boost::hash<Flyweight>()(f1)==
122                boost::hash<const value_type*>()(&f1.get()));
123 
124 #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
125     BOOST_TEST(std::hash<Flyweight>()(f1)==std::hash<Flyweight>()(c1));
126     BOOST_TEST(std::hash<Flyweight>()(f1)==
127                std::hash<const value_type*>()(&f1.get()));
128 #endif
129 #endif
130   }
131 }
132 
133 template<typename Flyweight,typename ForwardIterator>
test_basic_with_assign_template(ForwardIterator first,ForwardIterator last BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE (Flyweight))134 void test_basic_with_assign_template(
135   ForwardIterator first,ForwardIterator last
136   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
137 {
138   typedef typename Flyweight::value_type value_type;
139 
140   ForwardIterator it;
141 
142   test_basic_template<Flyweight>(first,last);
143 
144   for(it=first;it!=last;++it){
145     /* value construction */
146 
147     value_type v(*it);
148     Flyweight  f1(v);
149     Flyweight  f2(f1.get());
150     BOOST_TEST(f1.get()==v);
151     BOOST_TEST(f2.get()==v);
152     BOOST_TEST(f1==f2);
153 
154 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
155     value_type       v1(v);
156     const value_type v2(v);
157     Flyweight        fr1(std::move(v1));
158     Flyweight        fr2(std::move(v2));
159     BOOST_TEST(fr1==v);
160     BOOST_TEST(fr2==v);
161 #endif
162 
163     /* value assignment */
164 
165     Flyweight f3,f4;
166     f3=v;
167     f4=f1.get();
168     BOOST_TEST(f2.get()==v);
169     BOOST_TEST(f3.get()==v);
170     BOOST_TEST(f2==f3);
171 
172 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
173     Flyweight fr3;
174     fr3=value_type(*it);
175     BOOST_TEST(fr3.get()==value_type(*it));
176 #endif
177 
178     /* specialized algorithms */
179 
180     std::ostringstream oss1;
181     oss1<<f1;
182     std::istringstream iss1(oss1.str());
183     Flyweight f5;
184     iss1>>f5;
185     BOOST_TEST(f5==f1);
186   }
187 }
188 
189 template<
190   typename Flyweight1,typename Flyweight2,
191   typename ForwardIterator1,typename ForwardIterator2
192 >
test_basic_comparison_template(ForwardIterator1 first1,ForwardIterator1 last1,ForwardIterator2 first2 BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE (Flyweight1)BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE (Flyweight2))193 void test_basic_comparison_template(
194   ForwardIterator1 first1,ForwardIterator1 last1,
195   ForwardIterator2 first2
196   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight1)
197   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight2))
198 {
199   typedef typename Flyweight1::value_type value_type1;
200   typedef typename Flyweight2::value_type value_type2;
201 
202   for(;first1!=last1;++first1,++first2){
203     value_type1 v1=value_type1(*first1);
204     value_type2 v2=value_type2(*first2);
205     Flyweight1  f1(v1);
206     Flyweight2  f2(v2);
207 
208     BOOST_TEST((f1==f2)==(f1.get()==v2));
209     BOOST_TEST((f1< f2)==(f1.get()< v2));
210     BOOST_TEST((f1!=f2)==(f1.get()!=v2));
211     BOOST_TEST((f1> f2)==(f1.get()> v2));
212     BOOST_TEST((f1>=f2)==(f1.get()>=v2));
213     BOOST_TEST((f1<=f2)==(f1.get()<=v2));
214 
215 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
216     BOOST_TEST((f1==v2)==(f1.get()==v2));
217     BOOST_TEST((f1< v2)==(f1.get()< v2));
218     BOOST_TEST((f1!=v2)==(f1.get()!=v2));
219     BOOST_TEST((f1> v2)==(f1.get()> v2));
220     BOOST_TEST((f1>=v2)==(f1.get()>=v2));
221     BOOST_TEST((f1<=v2)==(f1.get()<=v2));
222 
223     BOOST_TEST((v1==f2)==(f1.get()==v2));
224     BOOST_TEST((v1< f2)==(f1.get()< v2));
225     BOOST_TEST((v1!=f2)==(f1.get()!=v2));
226     BOOST_TEST((v1> f2)==(f1.get()> v2));
227     BOOST_TEST((v1>=f2)==(f1.get()>=v2));
228     BOOST_TEST((v1<=f2)==(f1.get()<=v2));
229 #endif
230 
231   }
232 }
233 
234 template<typename FlyweightSpecifier>
test_basic_template(BOOST_EXPLICIT_TEMPLATE_TYPE (FlyweightSpecifier))235 void test_basic_template(BOOST_EXPLICIT_TEMPLATE_TYPE(FlyweightSpecifier))
236 {
237   typedef typename boost::mpl::apply1<
238     FlyweightSpecifier,int
239   >::type int_flyweight;
240 
241   typedef typename boost::mpl::apply1<
242     FlyweightSpecifier,std::string
243   >::type string_flyweight;
244 
245   typedef typename boost::mpl::apply1<
246     FlyweightSpecifier,char
247   >::type char_flyweight;
248 
249   typedef typename boost::mpl::apply1<
250     FlyweightSpecifier,
251     boost::flyweights::key_value<std::string,texture,from_texture_to_string>
252   >::type texture_flyweight;
253 
254   typedef typename boost::mpl::apply1<
255     FlyweightSpecifier,
256     boost::flyweights::key_value<int,factorization>
257   >::type factorization_flyweight;
258 
259   int ints[]={0,1,1,0,1,2,3,4,3,4,0,0};
260   test_basic_with_assign_template<int_flyweight>(
261     &ints[0],&ints[0]+LENGTHOF(ints));
262 
263   const char* words[]={"hello","boost","flyweight","boost","bye","c++","c++"};
264   test_basic_with_assign_template<string_flyweight>(
265     &words[0],&words[0]+LENGTHOF(words));
266 
267   const char* textures[]={"wood","grass","sand","granite","terracotta"};
268   test_basic_with_assign_template<texture_flyweight>(
269     &textures[0],&textures[0]+LENGTHOF(textures));
270 
271   int factorizations[]={1098,102387,90846,2223978};
272   test_basic_template<factorization_flyweight>(
273     &factorizations[0],&factorizations[0]+LENGTHOF(factorizations));
274 
275   char chars[]={0,2,4,5,1,1,1,3,4,1,1,0};
276   test_basic_comparison_template<int_flyweight,char_flyweight>(
277     &ints[0],&ints[0]+LENGTHOF(ints),&chars[0]);
278 
279   test_basic_comparison_template<string_flyweight,string_flyweight>(
280     &words[0],&words[0]+LENGTHOF(words)-1,&words[1]);
281 
282   test_basic_comparison_template<texture_flyweight,texture_flyweight>(
283     &textures[0],&textures[0]+LENGTHOF(textures)-1,&textures[1]);
284 
285 #if !defined(BOOST_NO_EXCEPTIONS)
286   typedef typename boost::mpl::apply1<
287     FlyweightSpecifier,
288     boost::flyweights::key_value<int,throwing_value,from_throwing_value_to_int>
289   >::type throwing_flyweight;
290 
291   try{
292     throwing_flyweight fw(0);
293   }catch(const throwing_value_exception&){}
294   try{
295     throwing_flyweight fw=throwing_flyweight(throwing_value());
296     (void)fw;
297   }catch(const throwing_value_exception&){}
298 #endif
299 
300 }
301 
302 #undef LENGTHOF
303 
304 #endif
305