unique_ptr_functions.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2014-2014.
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //
  9. // See http://www.boost.org/libs/move for documentation.
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. #include <boost/move/make_unique.hpp>
  13. #include <boost/core/lightweight_test.hpp>
  14. #include <cstring>
  15. struct A
  16. {
  17. int a, b, c;
  18. static int count;
  19. A() : a (999), b(1000), c(1001) {++count;}
  20. A(int a) : a (a), b(1000), c(1001) {++count;}
  21. A(int a, int b) : a (a), b(b), c(1001) {++count;}
  22. A(int a, int b, int c) : a (a), b(b), c(c) {++count;}
  23. A(const A&) {++count;}
  24. virtual ~A() {--count;}
  25. };
  26. int A::count = 0;
  27. struct B
  28. : public A
  29. {
  30. static int count;
  31. B() : A() {++count;}
  32. B(const B&) : A() {++count;}
  33. virtual ~B() {--count;}
  34. };
  35. int B::count = 0;
  36. void reset_counters()
  37. { A::count = B::count = 0; }
  38. static const unsigned PatternSize = 8;
  39. static const unsigned char ff_patternbuf[PatternSize] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  40. static const unsigned char ee_patternbuf[PatternSize] = { 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE };
  41. static const unsigned char dd_patternbuf[PatternSize] = { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD };
  42. static const unsigned char cc_patternbuf[PatternSize] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC };
  43. void volatile_memset(volatile void *p, int ch, std::size_t len)
  44. {
  45. volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
  46. for(std::size_t i = 0; i != len; ++i){
  47. *puch = (unsigned char)ch;
  48. ++puch;
  49. }
  50. }
  51. int volatile_memcmp(const volatile void *p1, const volatile void *p2, std::size_t len)
  52. {
  53. const volatile unsigned char *s1 = static_cast<const volatile unsigned char *>(p1);
  54. const volatile unsigned char *s2 = static_cast<const volatile unsigned char *>(p2);
  55. unsigned char u1, u2;
  56. for ( ; len-- ; s1++, s2++) {
  57. u1 = *s1;
  58. u2 = *s2;
  59. if (u1 != u2) {
  60. return (u1-u2);
  61. }
  62. }
  63. return 0;
  64. }
  65. void volatile_memcmp(volatile void *p, int ch, std::size_t len)
  66. {
  67. volatile unsigned char *puch = static_cast<volatile unsigned char *>(p);
  68. for(std::size_t i = 0; i != len; ++i){
  69. *puch = (unsigned char)ch;
  70. ++puch;
  71. }
  72. }
  73. #include <iostream>
  74. struct default_init
  75. {
  76. static void* operator new(std::size_t sz)
  77. {
  78. void *const p = ::operator new(sz);
  79. //Make sure they are not optimized out
  80. volatile_memset(p, 0xFF, sz);
  81. std::cout << "0xFF" << '\n';
  82. return p;
  83. }
  84. static void* operator new[](std::size_t sz)
  85. {
  86. void *const p = ::operator new[](sz);
  87. //Make sure they are not optimized out
  88. volatile_memset(p, 0xEE, sz);
  89. std::cout << "0xEE" << '\n';
  90. return p;
  91. }
  92. static void* operator new(std::size_t sz, const std::nothrow_t &)
  93. {
  94. void *const p = ::operator new(sz);
  95. //Make sure they are not optimized out
  96. volatile_memset(p, 0xDD, sz);
  97. std::cout << "0xDD" << '\n';
  98. return p;
  99. }
  100. static void* operator new[](std::size_t sz, const std::nothrow_t &)
  101. {
  102. void *const p = ::operator new[](sz);
  103. //Make sure they are not optimized out
  104. volatile_memset(p, 0xCC, sz);
  105. std::cout << "0xCC" << '\n';
  106. return p;
  107. }
  108. unsigned char buf[PatternSize];
  109. };
  110. namespace bml = ::boost::movelib;
  111. ////////////////////////////////
  112. // make_unique_single
  113. ////////////////////////////////
  114. namespace make_unique_single{
  115. void test()
  116. {
  117. //Single element deleter
  118. reset_counters();
  119. {
  120. bml::unique_ptr<default_init> p(bml::make_unique_definit<default_init>());
  121. BOOST_TEST(0 == volatile_memcmp(p.get(), ff_patternbuf, sizeof(ff_patternbuf)));
  122. }
  123. {
  124. bml::unique_ptr<default_init> p(bml::make_unique_nothrow_definit<default_init>());
  125. BOOST_TEST(0 == volatile_memcmp(p.get(), dd_patternbuf, sizeof(dd_patternbuf)));
  126. }
  127. BOOST_TEST(A::count == 0);
  128. {
  129. bml::unique_ptr<A> p(bml::make_unique<A>());
  130. BOOST_TEST(A::count == 1);
  131. BOOST_TEST(p->a == 999);
  132. BOOST_TEST(p->b == 1000);
  133. BOOST_TEST(p->c == 1001);
  134. }
  135. BOOST_TEST(A::count == 0);
  136. {
  137. bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0));
  138. BOOST_TEST(A::count == 1);
  139. BOOST_TEST(p->a == 0);
  140. BOOST_TEST(p->b == 1000);
  141. BOOST_TEST(p->c == 1001);
  142. }
  143. BOOST_TEST(A::count == 0);
  144. {
  145. bml::unique_ptr<A> p(bml::make_unique<A>(0, 1));
  146. BOOST_TEST(A::count == 1);
  147. BOOST_TEST(p->a == 0);
  148. BOOST_TEST(p->b == 1);
  149. BOOST_TEST(p->c == 1001);
  150. }
  151. BOOST_TEST(A::count == 0);
  152. {
  153. bml::unique_ptr<A> p(bml::make_unique_nothrow<A>(0, 1, 2));
  154. BOOST_TEST(A::count == 1);
  155. BOOST_TEST(p->a == 0);
  156. BOOST_TEST(p->b == 1);
  157. BOOST_TEST(p->c == 2);
  158. }
  159. BOOST_TEST(A::count == 0);
  160. }
  161. } //namespace make_unique_single{
  162. ////////////////////////////////
  163. // make_unique_array
  164. ////////////////////////////////
  165. namespace make_unique_array{
  166. void test()
  167. {
  168. //Array element
  169. reset_counters();
  170. {
  171. bml::unique_ptr<A[]> p(bml::make_unique<A[]>(10));
  172. BOOST_TEST(A::count == 10);
  173. for(int i = 0; i != 10; ++i){
  174. BOOST_TEST(p[i].a == 999);
  175. BOOST_TEST(p[i].b == 1000);
  176. BOOST_TEST(p[i].c == 1001);
  177. }
  178. }
  179. BOOST_TEST(A::count == 0);
  180. {
  181. bml::unique_ptr<A[]> p(bml::make_unique_nothrow<A[]>(10));
  182. BOOST_TEST(A::count == 10);
  183. for(int i = 0; i != 10; ++i){
  184. BOOST_TEST(p[i].a == 999);
  185. BOOST_TEST(p[i].b == 1000);
  186. BOOST_TEST(p[i].c == 1001);
  187. }
  188. }
  189. BOOST_TEST(A::count == 0);
  190. reset_counters();
  191. {
  192. bml::unique_ptr<default_init[]> p(bml::make_unique_definit<default_init[]>(10));
  193. for(unsigned i = 0; i != 10; ++i){
  194. BOOST_TEST(0 == volatile_memcmp(&p[i], ee_patternbuf, sizeof(ee_patternbuf)));
  195. }
  196. }
  197. reset_counters();
  198. {
  199. bml::unique_ptr<default_init[]> p(bml::make_unique_nothrow_definit<default_init[]>(10));
  200. for(unsigned i = 0; i != 10; ++i){
  201. BOOST_TEST(0 == volatile_memcmp(&p[i], cc_patternbuf, sizeof(cc_patternbuf)));
  202. }
  203. }
  204. }
  205. } //namespace make_unique_array{
  206. ////////////////////////////////
  207. // unique_compare
  208. ////////////////////////////////
  209. namespace unique_compare{
  210. void test()
  211. {
  212. //Single element deleter
  213. reset_counters();
  214. {
  215. bml::unique_ptr<A> pa(bml::make_unique<A>());
  216. bml::unique_ptr<A> pb(bml::make_unique<A>());
  217. BOOST_TEST(A::count == 2);
  218. //Take references to less and greater
  219. bml::unique_ptr<A> &rpl = pa < pb ? pa : pb;
  220. bml::unique_ptr<A> &rpg = pa < pb ? pb : pa;
  221. //Now test operations with .get()
  222. //Equal
  223. BOOST_TEST(rpl == rpl && rpl.get() == rpl.get());
  224. BOOST_TEST(!(rpl == rpg) && !(rpl.get() == rpg.get()));
  225. //Unequal
  226. BOOST_TEST(rpl != rpg && rpl.get() != rpg.get());
  227. BOOST_TEST(!(rpl != rpl) && !(rpl.get() != rpl.get()));
  228. //Less
  229. BOOST_TEST(rpl < rpg && rpl.get() < rpg.get());
  230. BOOST_TEST(!(rpg < rpl) && !(rpg.get() < rpl.get()));
  231. //Greater
  232. BOOST_TEST(rpg > rpl && rpg.get() > rpl.get());
  233. BOOST_TEST(!(rpg > rpg) && !(rpg.get() > rpg.get()));
  234. //Less or equal
  235. BOOST_TEST(rpl <= rpg && rpl.get() <= rpg.get());
  236. BOOST_TEST(rpl <= rpl && rpl.get() <= rpl.get());
  237. BOOST_TEST(!(rpg <= rpl) && !(rpg.get() <= rpl.get()));
  238. //Greater or equal
  239. BOOST_TEST(rpg >= rpl && rpg.get() >= rpl.get());
  240. BOOST_TEST(rpg >= rpg && rpg.get() >= rpg.get());
  241. BOOST_TEST(!(rpl >= rpg) && !(rpl.get() >= rpg.get()));
  242. }
  243. BOOST_TEST(A::count == 0);
  244. }
  245. } //namespace unique_compare{
  246. ////////////////////////////////
  247. // unique_compare_zero
  248. ////////////////////////////////
  249. namespace unique_compare_zero{
  250. void test()
  251. {
  252. //Single element deleter
  253. reset_counters();
  254. {
  255. bml::unique_ptr<A> pa(bml::make_unique<A>());
  256. bml::unique_ptr<A> pb;
  257. BOOST_TEST(A::count == 1);
  258. //Equal
  259. BOOST_TEST(!(pa == 0));
  260. BOOST_TEST(!(0 == pa));
  261. BOOST_TEST((pb == 0));
  262. BOOST_TEST((0 == pb));
  263. //Unequal
  264. BOOST_TEST((pa != 0));
  265. BOOST_TEST((0 != pa));
  266. BOOST_TEST(!(pb != 0));
  267. BOOST_TEST(!(0 != pb));
  268. //Less
  269. BOOST_TEST((pa < 0) == (pa.get() < (A*)0));
  270. BOOST_TEST((0 < pa) == ((A*)0 < pa.get()));
  271. BOOST_TEST((pb < 0) == (pb.get() < (A*)0));
  272. BOOST_TEST((0 < pb) == ((A*)0 < pb.get()));
  273. //Greater
  274. BOOST_TEST((pa > 0) == (pa.get() > (A*)0));
  275. BOOST_TEST((0 > pa) == ((A*)0 > pa.get()));
  276. BOOST_TEST((pb > 0) == (pb.get() > (A*)0));
  277. BOOST_TEST((0 > pb) == ((A*)0 > pb.get()));
  278. //Less or equal
  279. BOOST_TEST((pa <= 0) == (pa.get() <= (A*)0));
  280. BOOST_TEST((0 <= pa) == ((A*)0 <= pa.get()));
  281. BOOST_TEST((pb <= 0) == (pb.get() <= (A*)0));
  282. BOOST_TEST((0 <= pb) == ((A*)0 <= pb.get()));
  283. //Greater or equal
  284. BOOST_TEST((pa >= 0) == (pa.get() >= (A*)0));
  285. BOOST_TEST((0 >= pa) == ((A*)0 >= pa.get()));
  286. BOOST_TEST((pb >= 0) == (pb.get() >= (A*)0));
  287. BOOST_TEST((0 >= pb) == ((A*)0 >= pb.get()));
  288. }
  289. BOOST_TEST(A::count == 0);
  290. }
  291. } //namespace unique_compare_zero{
  292. ////////////////////////////////
  293. // unique_compare_nullptr
  294. ////////////////////////////////
  295. namespace unique_compare_nullptr{
  296. void test()
  297. {
  298. #if !defined(BOOST_NO_CXX11_NULLPTR)
  299. //Single element deleter
  300. reset_counters();
  301. {
  302. bml::unique_ptr<A> pa(bml::make_unique<A>());
  303. bml::unique_ptr<A> pb;
  304. BOOST_TEST(A::count == 1);
  305. //Equal
  306. BOOST_TEST(!(pa == nullptr));
  307. BOOST_TEST(!(nullptr == pa));
  308. BOOST_TEST((pb == nullptr));
  309. BOOST_TEST((nullptr == pb));
  310. //Unequal
  311. BOOST_TEST((pa != nullptr));
  312. BOOST_TEST((nullptr != pa));
  313. BOOST_TEST(!(pb != nullptr));
  314. BOOST_TEST(!(nullptr != pb));
  315. //Less
  316. BOOST_TEST((pa < nullptr) == (pa.get() < (A*)nullptr));
  317. BOOST_TEST((nullptr < pa) == ((A*)nullptr < pa.get()));
  318. BOOST_TEST((pb < nullptr) == (pb.get() < (A*)nullptr));
  319. BOOST_TEST((nullptr < pb) == ((A*)nullptr < pb.get()));
  320. //Greater
  321. BOOST_TEST((pa > nullptr) == (pa.get() > (A*)nullptr));
  322. BOOST_TEST((nullptr > pa) == ((A*)nullptr > pa.get()));
  323. BOOST_TEST((pb > nullptr) == (pb.get() > (A*)nullptr));
  324. BOOST_TEST((nullptr > pb) == ((A*)nullptr > pb.get()));
  325. //Less or equal
  326. BOOST_TEST((pa <= nullptr) == (pa.get() <= (A*)nullptr));
  327. BOOST_TEST((nullptr <= pa) == ((A*)nullptr <= pa.get()));
  328. BOOST_TEST((pb <= nullptr) == (pb.get() <= (A*)nullptr));
  329. BOOST_TEST((nullptr <= pb) == ((A*)nullptr <= pb.get()));
  330. //Greater or equal
  331. BOOST_TEST((pa >= nullptr) == (pa.get() >= (A*)nullptr));
  332. BOOST_TEST((nullptr >= pa) == ((A*)nullptr >= pa.get()));
  333. BOOST_TEST((pb >= nullptr) == (pb.get() >= (A*)nullptr));
  334. BOOST_TEST((nullptr >= pb) == ((A*)nullptr >= pb.get()));
  335. }
  336. BOOST_TEST(A::count == 0);
  337. #endif //#if !defined(BOOST_NO_CXX11_NULLPTR)
  338. }
  339. } //namespace unique_compare_nullptr{
  340. ////////////////////////////////
  341. // main
  342. ////////////////////////////////
  343. int main()
  344. {
  345. make_unique_single::test();
  346. make_unique_array::test();
  347. unique_compare::test();
  348. unique_compare_zero::test();
  349. unique_compare_nullptr::test();
  350. //Test results
  351. return boost::report_errors();
  352. }