test_basic_template.hpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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. #ifndef BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
  11. #define BOOST_FLYWEIGHT_TEST_BASIC_TEMPLATE_HPP
  12. #if defined(_MSC_VER)
  13. #pragma once
  14. #endif
  15. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  16. #include <boost/detail/lightweight_test.hpp>
  17. #include <boost/flyweight/key_value.hpp>
  18. #include <boost/mpl/apply.hpp>
  19. #include <boost/utility/value_init.hpp>
  20. #include <string>
  21. #include <sstream>
  22. #include "heavy_objects.hpp"
  23. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  24. #include <utility>
  25. #endif
  26. #if !defined(BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT)
  27. #include <boost/functional/hash.hpp>
  28. #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
  29. #include <functional>
  30. #endif
  31. #endif
  32. #define LENGTHOF(array) (sizeof(array)/sizeof((array)[0]))
  33. template<typename Flyweight,typename ForwardIterator>
  34. void test_basic_template(
  35. ForwardIterator first,ForwardIterator last
  36. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
  37. {
  38. typedef typename Flyweight::value_type value_type;
  39. ForwardIterator it;
  40. for(it=first;it!=last;++it){
  41. /* construct/copy/destroy */
  42. Flyweight f1(*it);
  43. Flyweight f2;
  44. Flyweight c1(f1);
  45. const Flyweight c2(static_cast<const Flyweight&>(f2));
  46. value_type v1(*it);
  47. boost::value_initialized<value_type> v2;
  48. BOOST_TEST(f1.get_key()==*it);
  49. BOOST_TEST((f1==f2)==(f1.get()==v2.data()));
  50. BOOST_TEST(f1==c1);
  51. BOOST_TEST(f2==c2);
  52. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  53. Flyweight cr1(std::move(c1));
  54. Flyweight cr2(std::move(c2));
  55. BOOST_TEST(f1==cr1);
  56. BOOST_TEST(f2==cr2);
  57. #endif
  58. #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX)
  59. /* testcase for https://svn.boost.org/trac/boost/ticket/10439 */
  60. Flyweight f3={};
  61. BOOST_TEST(f3==f2);
  62. #endif
  63. f1=((void)0,f1); /* self assignment warning */
  64. BOOST_TEST(f1==f1);
  65. c1=f2;
  66. BOOST_TEST(c1==f2);
  67. c1=f1;
  68. BOOST_TEST(c1==f1);
  69. /* convertibility to underlying type */
  70. BOOST_TEST(f1.get()==v1);
  71. /* identity of reference */
  72. BOOST_TEST(&f1.get()==&c1.get());
  73. /* modifiers */
  74. f1.swap(f1);
  75. BOOST_TEST(f1==c1);
  76. f1.swap(f2);
  77. BOOST_TEST(f1==c2);
  78. BOOST_TEST(f2==c1);
  79. boost::flyweights::swap(f1,f2);
  80. BOOST_TEST(f1==c1);
  81. BOOST_TEST(f2==c2);
  82. /* specialized algorithms */
  83. std::ostringstream oss1;
  84. oss1<<f1;
  85. std::ostringstream oss2;
  86. oss2<<f1.get();
  87. BOOST_TEST(oss1.str()==oss2.str());
  88. #if !defined(BOOST_FLYWEIGHT_DISABLE_HASH_SUPPORT)
  89. /* hash support */
  90. BOOST_TEST(boost::hash<Flyweight>()(f1)==boost::hash<Flyweight>()(c1));
  91. BOOST_TEST(boost::hash<Flyweight>()(f1)==
  92. boost::hash<const value_type*>()(&f1.get()));
  93. #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
  94. BOOST_TEST(std::hash<Flyweight>()(f1)==std::hash<Flyweight>()(c1));
  95. BOOST_TEST(std::hash<Flyweight>()(f1)==
  96. std::hash<const value_type*>()(&f1.get()));
  97. #endif
  98. #endif
  99. }
  100. }
  101. template<typename Flyweight,typename ForwardIterator>
  102. void test_basic_with_assign_template(
  103. ForwardIterator first,ForwardIterator last
  104. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight))
  105. {
  106. typedef typename Flyweight::value_type value_type;
  107. ForwardIterator it;
  108. test_basic_template<Flyweight>(first,last);
  109. for(it=first;it!=last;++it){
  110. /* value construction */
  111. value_type v(*it);
  112. Flyweight f1(v);
  113. Flyweight f2(f1.get());
  114. BOOST_TEST(f1.get()==v);
  115. BOOST_TEST(f2.get()==v);
  116. BOOST_TEST(f1==f2);
  117. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  118. value_type v1(v);
  119. const value_type v2(v);
  120. Flyweight fr1(std::move(v1));
  121. Flyweight fr2(std::move(v2));
  122. BOOST_TEST(fr1==v);
  123. BOOST_TEST(fr2==v);
  124. #endif
  125. /* value assignment */
  126. Flyweight f3,f4;
  127. f3=v;
  128. f4=f1.get();
  129. BOOST_TEST(f2.get()==v);
  130. BOOST_TEST(f3.get()==v);
  131. BOOST_TEST(f2==f3);
  132. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  133. Flyweight fr3;
  134. fr3=value_type(*it);
  135. BOOST_TEST(fr3.get()==value_type(*it));
  136. #endif
  137. /* specialized algorithms */
  138. std::ostringstream oss1;
  139. oss1<<f1;
  140. std::istringstream iss1(oss1.str());
  141. Flyweight f5;
  142. iss1>>f5;
  143. BOOST_TEST(f5==f1);
  144. }
  145. }
  146. template<
  147. typename Flyweight1,typename Flyweight2,
  148. typename ForwardIterator1,typename ForwardIterator2
  149. >
  150. void test_basic_comparison_template(
  151. ForwardIterator1 first1,ForwardIterator1 last1,
  152. ForwardIterator2 first2
  153. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight1)
  154. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Flyweight2))
  155. {
  156. typedef typename Flyweight1::value_type value_type1;
  157. typedef typename Flyweight2::value_type value_type2;
  158. for(;first1!=last1;++first1,++first2){
  159. value_type1 v1=value_type1(*first1);
  160. value_type2 v2=value_type2(*first2);
  161. Flyweight1 f1(v1);
  162. Flyweight2 f2(v2);
  163. BOOST_TEST((f1==f2)==(f1.get()==v2));
  164. BOOST_TEST((f1< f2)==(f1.get()< v2));
  165. BOOST_TEST((f1!=f2)==(f1.get()!=v2));
  166. BOOST_TEST((f1> f2)==(f1.get()> v2));
  167. BOOST_TEST((f1>=f2)==(f1.get()>=v2));
  168. BOOST_TEST((f1<=f2)==(f1.get()<=v2));
  169. #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
  170. BOOST_TEST((f1==v2)==(f1.get()==v2));
  171. BOOST_TEST((f1< v2)==(f1.get()< v2));
  172. BOOST_TEST((f1!=v2)==(f1.get()!=v2));
  173. BOOST_TEST((f1> v2)==(f1.get()> v2));
  174. BOOST_TEST((f1>=v2)==(f1.get()>=v2));
  175. BOOST_TEST((f1<=v2)==(f1.get()<=v2));
  176. BOOST_TEST((v1==f2)==(f1.get()==v2));
  177. BOOST_TEST((v1< f2)==(f1.get()< v2));
  178. BOOST_TEST((v1!=f2)==(f1.get()!=v2));
  179. BOOST_TEST((v1> f2)==(f1.get()> v2));
  180. BOOST_TEST((v1>=f2)==(f1.get()>=v2));
  181. BOOST_TEST((v1<=f2)==(f1.get()<=v2));
  182. #endif
  183. }
  184. }
  185. template<typename FlyweightSpecifier>
  186. void test_basic_template(BOOST_EXPLICIT_TEMPLATE_TYPE(FlyweightSpecifier))
  187. {
  188. typedef typename boost::mpl::apply1<
  189. FlyweightSpecifier,int
  190. >::type int_flyweight;
  191. typedef typename boost::mpl::apply1<
  192. FlyweightSpecifier,std::string
  193. >::type string_flyweight;
  194. typedef typename boost::mpl::apply1<
  195. FlyweightSpecifier,char
  196. >::type char_flyweight;
  197. typedef typename boost::mpl::apply1<
  198. FlyweightSpecifier,
  199. boost::flyweights::key_value<std::string,texture,from_texture_to_string>
  200. >::type texture_flyweight;
  201. typedef typename boost::mpl::apply1<
  202. FlyweightSpecifier,
  203. boost::flyweights::key_value<int,factorization>
  204. >::type factorization_flyweight;
  205. int ints[]={0,1,1,0,1,2,3,4,3,4,0,0};
  206. test_basic_with_assign_template<int_flyweight>(
  207. &ints[0],&ints[0]+LENGTHOF(ints));
  208. const char* words[]={"hello","boost","flyweight","boost","bye","c++","c++"};
  209. test_basic_with_assign_template<string_flyweight>(
  210. &words[0],&words[0]+LENGTHOF(words));
  211. const char* textures[]={"wood","grass","sand","granite","terracotta"};
  212. test_basic_with_assign_template<texture_flyweight>(
  213. &textures[0],&textures[0]+LENGTHOF(textures));
  214. int factorizations[]={1098,102387,90846,2223978};
  215. test_basic_template<factorization_flyweight>(
  216. &factorizations[0],&factorizations[0]+LENGTHOF(factorizations));
  217. char chars[]={0,2,4,5,1,1,1,3,4,1,1,0};
  218. test_basic_comparison_template<int_flyweight,char_flyweight>(
  219. &ints[0],&ints[0]+LENGTHOF(ints),&chars[0]);
  220. test_basic_comparison_template<string_flyweight,string_flyweight>(
  221. &words[0],&words[0]+LENGTHOF(words)-1,&words[1]);
  222. test_basic_comparison_template<texture_flyweight,texture_flyweight>(
  223. &textures[0],&textures[0]+LENGTHOF(textures)-1,&textures[1]);
  224. #if !defined(BOOST_NO_EXCEPTIONS)
  225. typedef typename boost::mpl::apply1<
  226. FlyweightSpecifier,
  227. boost::flyweights::key_value<int,throwing_value,from_throwing_value_to_int>
  228. >::type throwing_flyweight;
  229. try{
  230. throwing_flyweight fw(0);
  231. }catch(const throwing_value_exception&){}
  232. try{
  233. throwing_flyweight fw=throwing_flyweight(throwing_value());
  234. (void)fw;
  235. }catch(const throwing_value_exception&){}
  236. #endif
  237. }
  238. #undef LENGTHOF
  239. #endif