You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

small_vector.cpp 39 kB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150
  1. /**
  2. * \file dnn/test/common/small_vector.cpp
  3. * MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  4. *
  5. * Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  6. *
  7. * Unless required by applicable law or agreed to in writing,
  8. * software distributed under the License is distributed on an
  9. * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. */
  11. //===- llvm/unittest/ADT/SmallVectorTest.cpp ------------------------------===//
  12. //
  13. // The LLVM Compiler Infrastructure
  14. //
  15. // This file is distributed under the University of Illinois Open Source
  16. // License. See LICENSE.TXT for details.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. //
  20. // SmallVector unit tests.
  21. //
  22. //===----------------------------------------------------------------------===//
  23. /**
  24. * \file common/small_vector.cpp
  25. *
  26. * This file is part of MegBrain, a deep learning framework developed by Megvii.
  27. *
  28. * \copyright Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  29. */
  30. #include "megdnn/thin/small_vector.h"
  31. #include <gtest/gtest.h>
  32. #include <cstdarg>
  33. #include <list>
  34. #include <unordered_set>
  35. using namespace megdnn;
  36. namespace {
  37. /// A helper class that counts the total number of constructor and
  38. /// destructor calls.
  39. class Constructable {
  40. private:
  41. static int num_constructor_calls;
  42. static int num_move_constructor_calls;
  43. static int num_copy_constructor_calls;
  44. static int num_deconstructor_calls;
  45. static int num_assignment_calls;
  46. static int num_move_assignment_calls;
  47. static int num_copy_assignment_calls;
  48. static std::unordered_set<const Constructable*> destroyed_mem;
  49. bool m_constructed;
  50. int m_value;
  51. int m_id;
  52. public:
  53. Constructable() : m_constructed(true), m_value(0) {
  54. ++num_constructor_calls;
  55. m_id = num_constructor_calls;
  56. destroyed_mem.erase(this);
  57. }
  58. Constructable(int val) : m_constructed(true), m_value(val) {
  59. ++num_constructor_calls;
  60. m_id = num_constructor_calls;
  61. destroyed_mem.erase(this);
  62. }
  63. Constructable(const Constructable& src) : m_constructed(true) {
  64. m_value = src.m_value;
  65. ++num_constructor_calls;
  66. m_id = num_constructor_calls;
  67. EXPECT_TRUE(destroyed_mem.find(&src) == destroyed_mem.end());
  68. destroyed_mem.erase(this);
  69. }
  70. Constructable(Constructable&& src) : m_constructed(true) {
  71. m_value = src.m_value;
  72. ++num_constructor_calls;
  73. ++num_move_constructor_calls;
  74. m_id = num_constructor_calls;
  75. EXPECT_TRUE(destroyed_mem.find(&src) == destroyed_mem.end());
  76. destroyed_mem.erase(this);
  77. }
  78. ~Constructable() {
  79. EXPECT_TRUE(m_constructed);
  80. ++num_deconstructor_calls;
  81. m_constructed = false;
  82. destroyed_mem.insert(this);
  83. }
  84. Constructable& operator=(const Constructable& src) {
  85. EXPECT_TRUE(m_constructed);
  86. m_value = src.m_value;
  87. ++num_assignment_calls;
  88. ++num_copy_assignment_calls;
  89. m_id = src.m_id;
  90. EXPECT_TRUE(destroyed_mem.find(&src) == destroyed_mem.end());
  91. return *this;
  92. }
  93. Constructable& operator=(Constructable&& src) {
  94. EXPECT_TRUE(m_constructed);
  95. m_value = src.m_value;
  96. ++num_assignment_calls;
  97. ++num_move_assignment_calls;
  98. m_id = src.m_id;
  99. return *this;
  100. }
  101. int get_value() const { return abs(m_value); }
  102. static void reset() {
  103. num_constructor_calls = 0;
  104. num_move_constructor_calls = 0;
  105. num_copy_constructor_calls = 0;
  106. num_deconstructor_calls = 0;
  107. num_assignment_calls = 0;
  108. num_move_assignment_calls = 0;
  109. num_copy_assignment_calls = 0;
  110. destroyed_mem.clear();
  111. }
  112. static int get_num_constructor_calls() { return num_constructor_calls; }
  113. static int get_num_move_constructor_calls() {
  114. return num_move_constructor_calls;
  115. }
  116. static int get_num_copy_constructor_calls() {
  117. return num_copy_constructor_calls;
  118. }
  119. static int get_num_destructor_calls() { return num_deconstructor_calls; }
  120. static int get_num_assignment_calls() { return num_assignment_calls; }
  121. static int get_num_move_assignment_calls() {
  122. return num_move_assignment_calls;
  123. }
  124. static int get_num_copy_assignment_calls() {
  125. return num_copy_assignment_calls;
  126. }
  127. bool operator==(const Constructable& rhs) const {
  128. return this->get_value() == rhs.get_value();
  129. }
  130. bool operator!=(const Constructable& rhs) const {
  131. return this->get_value() != rhs.get_value();
  132. }
  133. };
  134. int Constructable::num_constructor_calls;
  135. int Constructable::num_copy_constructor_calls;
  136. int Constructable::num_move_constructor_calls;
  137. int Constructable::num_deconstructor_calls;
  138. int Constructable::num_assignment_calls;
  139. int Constructable::num_copy_assignment_calls;
  140. int Constructable::num_move_assignment_calls;
  141. std::unordered_set<const Constructable*> Constructable::destroyed_mem;
  142. struct NonCopyable {
  143. NonCopyable() {}
  144. NonCopyable(NonCopyable&&) {}
  145. NonCopyable& operator=(NonCopyable&&) { return *this; }
  146. private:
  147. NonCopyable(const NonCopyable&) = delete;
  148. NonCopyable& operator=(const NonCopyable&) = delete;
  149. };
  150. struct MoveOnly {
  151. int val;
  152. MoveOnly(int v) : val{v} {}
  153. MoveOnly(MoveOnly&& rhs) : val{rhs.val} { rhs.val = 0; }
  154. MoveOnly& operator=(MoveOnly&& rhs) {
  155. val = rhs.val;
  156. rhs.val = 0;
  157. return *this;
  158. }
  159. private:
  160. MoveOnly(const MoveOnly&) = delete;
  161. MoveOnly& operator=(const MoveOnly&) = delete;
  162. };
  163. __attribute__((__unused__)) void compile_test() {
  164. SmallVector<NonCopyable, 0> v;
  165. v.resize(42);
  166. }
  167. class SmallVectorTestBase : public testing::Test {
  168. protected:
  169. void SetUp() override { Constructable::reset(); }
  170. template <typename VectorT>
  171. void assert_empty(VectorT& v) {
  172. // Size tests
  173. EXPECT_EQ(0u, v.size());
  174. EXPECT_TRUE(v.empty());
  175. // Iterator tests
  176. EXPECT_TRUE(v.begin() == v.end());
  177. }
  178. // Assert that v contains the specified values, in order.
  179. template <typename VectorT>
  180. void assert_values_in_order(VectorT& v, size_t size, ...) {
  181. EXPECT_EQ(size, v.size());
  182. va_list ap;
  183. va_start(ap, size);
  184. for (size_t i = 0; i < size; ++i) {
  185. int m_value = va_arg(ap, int);
  186. EXPECT_EQ(m_value, v[i].get_value());
  187. }
  188. va_end(ap);
  189. }
  190. // Generate a sequence of values to initialize the vector.
  191. template <typename VectorT>
  192. void make_sequence(VectorT& v, int start, int end) {
  193. for (int i = start; i <= end; ++i) {
  194. v.push_back(Constructable(i));
  195. }
  196. }
  197. };
  198. // Test fixture class
  199. template <typename VectorT>
  200. class SmallVectorTest : public SmallVectorTestBase {
  201. protected:
  202. VectorT the_vector;
  203. VectorT other_vector;
  204. };
  205. typedef ::testing::Types<
  206. SmallVector<Constructable, 0>, SmallVector<Constructable, 1>,
  207. SmallVector<Constructable, 2>, SmallVector<Constructable, 4>,
  208. SmallVector<Constructable, 5>>
  209. SmallVectorTestTypes;
  210. TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes);
  211. // Constructor test.
  212. TYPED_TEST(SmallVectorTest, ConstructorNonIterTest) {
  213. SCOPED_TRACE("ConstructorTest");
  214. this->the_vector = SmallVector<Constructable, 2>(2, 2);
  215. this->assert_values_in_order(this->the_vector, 2u, 2, 2);
  216. }
  217. // Constructor test.
  218. TYPED_TEST(SmallVectorTest, ConstructorIterTest) {
  219. SCOPED_TRACE("ConstructorTest");
  220. int arr[] = {1, 2, 3};
  221. this->the_vector =
  222. SmallVector<Constructable, 4>(std::begin(arr), std::end(arr));
  223. this->assert_values_in_order(this->the_vector, 3u, 1, 2, 3);
  224. }
  225. // New vector test.
  226. TYPED_TEST(SmallVectorTest, EmptyVectorTest) {
  227. SCOPED_TRACE("EmptyVectorTest");
  228. this->assert_empty(this->the_vector);
  229. EXPECT_TRUE(this->the_vector.rbegin() == this->the_vector.rend());
  230. EXPECT_EQ(0, Constructable::get_num_constructor_calls());
  231. EXPECT_EQ(0, Constructable::get_num_destructor_calls());
  232. }
  233. // Simple insertions and deletions.
  234. TYPED_TEST(SmallVectorTest, PushPopTest) {
  235. SCOPED_TRACE("PushPopTest");
  236. // Track whether the vector will potentially have to grow.
  237. bool require_growth = this->the_vector.capacity() < 3;
  238. // Push an element
  239. this->the_vector.push_back(Constructable(1));
  240. // Size tests
  241. this->assert_values_in_order(this->the_vector, 1u, 1);
  242. EXPECT_FALSE(this->the_vector.begin() == this->the_vector.end());
  243. EXPECT_FALSE(this->the_vector.empty());
  244. // Push another element
  245. this->the_vector.push_back(Constructable(2));
  246. this->assert_values_in_order(this->the_vector, 2u, 1, 2);
  247. // Insert at beginning
  248. this->the_vector.insert(this->the_vector.begin(), this->the_vector[1]);
  249. this->assert_values_in_order(this->the_vector, 3u, 2, 1, 2);
  250. // Pop one element
  251. this->the_vector.pop_back();
  252. this->assert_values_in_order(this->the_vector, 2u, 2, 1);
  253. // Pop remaining elements
  254. this->the_vector.pop_back();
  255. this->the_vector.pop_back();
  256. this->assert_empty(this->the_vector);
  257. // Check number of constructor calls. Should be 2 for each list element,
  258. // one for the argument to push_back, one for the argument to insert,
  259. // and one for the list element itself.
  260. if (!require_growth) {
  261. // Original test expected number is 5, however, after fixing the bug of
  262. // out of range while inserting element within vector, the
  263. // CopyConstructor would be called 1 more times.
  264. EXPECT_EQ(6, Constructable::get_num_constructor_calls());
  265. EXPECT_EQ(6, Constructable::get_num_destructor_calls());
  266. } else {
  267. // If we had to grow the vector, these only have a lower bound, but
  268. // should
  269. // always be equal.
  270. EXPECT_LE(5, Constructable::get_num_constructor_calls());
  271. EXPECT_EQ(Constructable::get_num_constructor_calls(),
  272. Constructable::get_num_destructor_calls());
  273. }
  274. }
  275. // Clear test.
  276. TYPED_TEST(SmallVectorTest, ClearTest) {
  277. SCOPED_TRACE("ClearTest");
  278. this->the_vector.reserve(2);
  279. this->make_sequence(this->the_vector, 1, 2);
  280. this->the_vector.clear();
  281. this->assert_empty(this->the_vector);
  282. EXPECT_EQ(4, Constructable::get_num_constructor_calls());
  283. EXPECT_EQ(4, Constructable::get_num_destructor_calls());
  284. }
  285. // Resize smaller test.
  286. TYPED_TEST(SmallVectorTest, ResizeShrinkTest) {
  287. SCOPED_TRACE("ResizeShrinkTest");
  288. this->the_vector.reserve(3);
  289. this->make_sequence(this->the_vector, 1, 3);
  290. this->the_vector.resize(1);
  291. this->assert_values_in_order(this->the_vector, 1u, 1);
  292. EXPECT_EQ(6, Constructable::get_num_constructor_calls());
  293. EXPECT_EQ(5, Constructable::get_num_destructor_calls());
  294. }
  295. // Resize bigger test.
  296. TYPED_TEST(SmallVectorTest, ResizeGrowTest) {
  297. SCOPED_TRACE("ResizeGrowTest");
  298. this->the_vector.resize(2);
  299. EXPECT_EQ(2, Constructable::get_num_constructor_calls());
  300. EXPECT_EQ(0, Constructable::get_num_destructor_calls());
  301. EXPECT_EQ(2u, this->the_vector.size());
  302. }
  303. TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) {
  304. this->the_vector.resize(2);
  305. Constructable::reset();
  306. this->the_vector.resize(4);
  307. size_t ctors = Constructable::get_num_constructor_calls();
  308. EXPECT_TRUE(ctors == 2 || ctors == 4);
  309. size_t movectors = Constructable::get_num_move_constructor_calls();
  310. EXPECT_TRUE(movectors == 0 || movectors == 2);
  311. size_t dtors = Constructable::get_num_destructor_calls();
  312. EXPECT_TRUE(dtors == 0 || dtors == 2);
  313. }
  314. // Resize with fill m_value.
  315. TYPED_TEST(SmallVectorTest, ResizeFillTest) {
  316. SCOPED_TRACE("ResizeFillTest");
  317. this->the_vector.resize(3, Constructable(77));
  318. this->assert_values_in_order(this->the_vector, 3u, 77, 77, 77);
  319. }
  320. // Overflow past fixed size.
  321. TYPED_TEST(SmallVectorTest, OverflowTest) {
  322. SCOPED_TRACE("OverflowTest");
  323. // Push more elements than the fixed size.
  324. this->make_sequence(this->the_vector, 1, 10);
  325. // Test size and values.
  326. EXPECT_EQ(10u, this->the_vector.size());
  327. for (int i = 0; i < 10; ++i) {
  328. EXPECT_EQ(i + 1, this->the_vector[i].get_value());
  329. }
  330. // Now resize back to fixed size.
  331. this->the_vector.resize(1);
  332. this->assert_values_in_order(this->the_vector, 1u, 1);
  333. }
  334. // Iteration tests.
  335. TYPED_TEST(SmallVectorTest, IterationTest) {
  336. this->make_sequence(this->the_vector, 1, 2);
  337. // Forward Iteration
  338. typename TypeParam::iterator it = this->the_vector.begin();
  339. EXPECT_TRUE(*it == this->the_vector.front());
  340. EXPECT_TRUE(*it == this->the_vector[0]);
  341. EXPECT_EQ(1, it->get_value());
  342. ++it;
  343. EXPECT_TRUE(*it == this->the_vector[1]);
  344. EXPECT_TRUE(*it == this->the_vector.back());
  345. EXPECT_EQ(2, it->get_value());
  346. ++it;
  347. EXPECT_TRUE(it == this->the_vector.end());
  348. --it;
  349. EXPECT_TRUE(*it == this->the_vector[1]);
  350. EXPECT_EQ(2, it->get_value());
  351. --it;
  352. EXPECT_TRUE(*it == this->the_vector[0]);
  353. EXPECT_EQ(1, it->get_value());
  354. // Reverse Iteration
  355. typename TypeParam::reverse_iterator rit = this->the_vector.rbegin();
  356. EXPECT_TRUE(*rit == this->the_vector[1]);
  357. EXPECT_EQ(2, rit->get_value());
  358. ++rit;
  359. EXPECT_TRUE(*rit == this->the_vector[0]);
  360. EXPECT_EQ(1, rit->get_value());
  361. ++rit;
  362. EXPECT_TRUE(rit == this->the_vector.rend());
  363. --rit;
  364. EXPECT_TRUE(*rit == this->the_vector[0]);
  365. EXPECT_EQ(1, rit->get_value());
  366. --rit;
  367. EXPECT_TRUE(*rit == this->the_vector[1]);
  368. EXPECT_EQ(2, rit->get_value());
  369. }
  370. // Swap test.
  371. TYPED_TEST(SmallVectorTest, SwapTest) {
  372. SCOPED_TRACE("SwapTest");
  373. this->make_sequence(this->the_vector, 1, 2);
  374. this->make_sequence(this->other_vector, 1, 4);
  375. std::swap(this->the_vector, this->other_vector);
  376. this->assert_values_in_order(this->the_vector, 4u, 1, 2, 3, 4);
  377. this->assert_values_in_order(this->other_vector, 2u, 1, 2);
  378. }
  379. // Symmetric to previoud Swap Test.
  380. TYPED_TEST(SmallVectorTest, SwapReverseTest) {
  381. SCOPED_TRACE("SwapReverseTest");
  382. this->make_sequence(this->the_vector, 1, 2);
  383. this->make_sequence(this->other_vector, 1, 4);
  384. std::swap(this->other_vector, this->the_vector);
  385. this->assert_values_in_order(this->the_vector, 4u, 1, 2, 3, 4);
  386. this->assert_values_in_order(this->other_vector, 2u, 1, 2);
  387. }
  388. // Swap two vectors with different default size N.
  389. TYPED_TEST(SmallVectorTest, SwapSpecificSizeWithoutGrowingTest) {
  390. SCOPED_TRACE("SwapSpecificSizeWithoutGrowingTest");
  391. SmallVector<Constructable, 3> other_vector;
  392. // not grow.
  393. this->make_sequence(other_vector, 1, 2);
  394. this->make_sequence(this->the_vector, 1, 3);
  395. std::swap(other_vector, this->the_vector);
  396. this->assert_values_in_order(other_vector, 3u, 1, 2, 3);
  397. this->assert_values_in_order(this->the_vector, 2u, 1, 2);
  398. }
  399. // Swap two vectors with different default size N.
  400. TYPED_TEST(SmallVectorTest, SwapSpecificSizeWithGrowingTest) {
  401. SCOPED_TRACE("SwapSpecificSizeWithGrowingTest");
  402. SmallVector<Constructable, 3> other_vector;
  403. // grow
  404. this->make_sequence(other_vector, 1, 4);
  405. this->make_sequence(this->the_vector, 1, 3);
  406. std::swap(other_vector, this->the_vector);
  407. this->assert_values_in_order(other_vector, 3u, 1, 2, 3);
  408. this->assert_values_in_order(this->the_vector, 4u, 1, 2, 3, 4);
  409. }
  410. // Append test
  411. TYPED_TEST(SmallVectorTest, AppendTest) {
  412. SCOPED_TRACE("AppendTest");
  413. this->make_sequence(this->other_vector, 2, 3);
  414. this->the_vector.push_back(Constructable(1));
  415. this->the_vector.append(this->other_vector.begin(),
  416. this->other_vector.end());
  417. this->assert_values_in_order(this->the_vector, 3u, 1, 2, 3);
  418. }
  419. // Append repeated test
  420. TYPED_TEST(SmallVectorTest, AppendRepeatedTest) {
  421. SCOPED_TRACE("AppendRepeatedTest");
  422. this->the_vector.push_back(Constructable(1));
  423. this->the_vector.append(2, Constructable(77));
  424. this->assert_values_in_order(this->the_vector, 3u, 1, 77, 77);
  425. }
  426. // Append test
  427. TYPED_TEST(SmallVectorTest, AppendNonIterTest) {
  428. SCOPED_TRACE("AppendRepeatedTest");
  429. this->the_vector.push_back(Constructable(1));
  430. this->the_vector.append(2, 7);
  431. this->assert_values_in_order(this->the_vector, 3u, 1, 7, 7);
  432. }
  433. struct OutputIterator {
  434. typedef std::output_iterator_tag iterator_category;
  435. typedef int value_type;
  436. typedef int difference_type;
  437. typedef value_type* pointer;
  438. typedef value_type& reference;
  439. operator int() { return 2; }
  440. operator Constructable() { return 7; }
  441. };
  442. TYPED_TEST(SmallVectorTest, AppendRepeatedNonForwardIterator) {
  443. SCOPED_TRACE("AppendRepeatedTest");
  444. this->the_vector.push_back(Constructable(1));
  445. this->the_vector.append(OutputIterator(), OutputIterator());
  446. this->assert_values_in_order(this->the_vector, 3u, 1, 7, 7);
  447. }
  448. // Assign test
  449. TYPED_TEST(SmallVectorTest, AssignTest) {
  450. SCOPED_TRACE("AssignTest");
  451. this->the_vector.push_back(Constructable(1));
  452. this->the_vector.assign(2, Constructable(77));
  453. this->assert_values_in_order(this->the_vector, 2u, 77, 77);
  454. }
  455. // Assign test
  456. TYPED_TEST(SmallVectorTest, AssignRangeTest) {
  457. SCOPED_TRACE("AssignTest");
  458. this->the_vector.push_back(Constructable(1));
  459. int arr[] = {1, 2, 3};
  460. this->the_vector.assign(std::begin(arr), std::end(arr));
  461. this->assert_values_in_order(this->the_vector, 3u, 1, 2, 3);
  462. }
  463. // Assign test
  464. TYPED_TEST(SmallVectorTest, AssignNonIterTest) {
  465. SCOPED_TRACE("AssignTest");
  466. this->the_vector.push_back(Constructable(1));
  467. this->the_vector.assign(2, 7);
  468. this->assert_values_in_order(this->the_vector, 2u, 7, 7);
  469. }
  470. // Move-assign test
  471. TYPED_TEST(SmallVectorTest, MoveAssignTest) {
  472. SCOPED_TRACE("MoveAssignTest");
  473. // Set up our vector with a single element, but enough capacity for 4.
  474. this->the_vector.reserve(4);
  475. this->the_vector.push_back(Constructable(1));
  476. // Set up the other vector with 2 elements.
  477. this->other_vector.push_back(Constructable(2));
  478. this->other_vector.push_back(Constructable(3));
  479. // Move-assign from the other vector.
  480. this->the_vector = std::move(this->other_vector);
  481. // Make sure we have the right result.
  482. this->assert_values_in_order(this->the_vector, 2u, 2, 3);
  483. // Make sure the # of constructor/destructor calls line up. There
  484. // are two live objects after clearing the other vector.
  485. this->other_vector.clear();
  486. EXPECT_EQ(Constructable::get_num_constructor_calls() - 2,
  487. Constructable::get_num_destructor_calls());
  488. // There shouldn't be any live objects any more.
  489. this->the_vector.clear();
  490. EXPECT_EQ(Constructable::get_num_constructor_calls(),
  491. Constructable::get_num_destructor_calls());
  492. }
  493. // Erase a single element
  494. TYPED_TEST(SmallVectorTest, EraseTest) {
  495. SCOPED_TRACE("EraseTest");
  496. this->make_sequence(this->the_vector, 1, 3);
  497. const auto& the_const_vector = this->the_vector;
  498. this->the_vector.erase(the_const_vector.begin());
  499. this->assert_values_in_order(this->the_vector, 2u, 2, 3);
  500. }
  501. // Erase a range of elements
  502. TYPED_TEST(SmallVectorTest, EraseRangeTest) {
  503. SCOPED_TRACE("EraseRangeTest");
  504. this->make_sequence(this->the_vector, 1, 3);
  505. const auto& the_const_vector = this->the_vector;
  506. this->the_vector.erase(the_const_vector.begin(),
  507. the_const_vector.begin() + 2);
  508. this->assert_values_in_order(this->the_vector, 1u, 3);
  509. }
  510. // Insert a single element.
  511. TYPED_TEST(SmallVectorTest, InsertTest) {
  512. SCOPED_TRACE("InsertTest");
  513. this->make_sequence(this->the_vector, 1, 3);
  514. typename TypeParam::iterator it = this->the_vector.insert(
  515. this->the_vector.begin() + 1, Constructable(77));
  516. EXPECT_EQ(this->the_vector.begin() + 1, it);
  517. this->assert_values_in_order(this->the_vector, 4u, 1, 77, 2, 3);
  518. }
  519. // Insert a copy of a single element.
  520. TYPED_TEST(SmallVectorTest, InsertCopy) {
  521. SCOPED_TRACE("InsertTest");
  522. this->make_sequence(this->the_vector, 1, 3);
  523. Constructable c(77);
  524. typename TypeParam::iterator it =
  525. this->the_vector.insert(this->the_vector.begin() + 1, c);
  526. EXPECT_EQ(this->the_vector.begin() + 1, it);
  527. this->assert_values_in_order(this->the_vector, 4u, 1, 77, 2, 3);
  528. }
  529. // Insert repeated elements.
  530. TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
  531. SCOPED_TRACE("InsertRepeatedTest");
  532. this->make_sequence(this->the_vector, 1, 4);
  533. Constructable::reset();
  534. auto it = this->the_vector.insert(this->the_vector.begin() + 1, 2,
  535. Constructable(16));
  536. // Move construct the top element into newly allocated space, and optionally
  537. // reallocate the whole buffer, move constructing into it.
  538. // FIXME: This is inefficient, we shouldn't move things into newly allocated
  539. // space, then move them up/around, there should only be 2 or 4 move
  540. // constructions here.
  541. EXPECT_TRUE(Constructable::get_num_move_constructor_calls() == 2 ||
  542. Constructable::get_num_move_constructor_calls() == 6);
  543. // Move assign the next two to shift them up and make a gap.
  544. EXPECT_EQ(1, Constructable::get_num_move_assignment_calls());
  545. // Copy construct the two new elements from the parameter.
  546. EXPECT_EQ(2, Constructable::get_num_copy_assignment_calls());
  547. // All without any copy construction.
  548. // EXPECT_EQ(0, Constructable::get_num_copy_constructor_calls());
  549. EXPECT_EQ(this->the_vector.begin() + 1, it);
  550. this->assert_values_in_order(this->the_vector, 6u, 1, 16, 16, 2, 3, 4);
  551. }
  552. TYPED_TEST(SmallVectorTest, InsertRepeatedNonIterTest) {
  553. SCOPED_TRACE("InsertRepeatedTest");
  554. this->make_sequence(this->the_vector, 1, 4);
  555. Constructable::reset();
  556. auto it = this->the_vector.insert(this->the_vector.begin() + 1, 2, 7);
  557. EXPECT_EQ(this->the_vector.begin() + 1, it);
  558. this->assert_values_in_order(this->the_vector, 6u, 1, 7, 7, 2, 3, 4);
  559. }
  560. TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) {
  561. SCOPED_TRACE("InsertRepeatedTest");
  562. this->make_sequence(this->the_vector, 1, 4);
  563. Constructable::reset();
  564. auto it = this->the_vector.insert(this->the_vector.end(), 2,
  565. Constructable(16));
  566. // Just copy construct them into newly allocated space
  567. // EXPECT_EQ(2, Constructable::get_num_copy_constructor_calls());
  568. // Move everything across if reallocation is needed.
  569. EXPECT_TRUE(Constructable::get_num_move_constructor_calls() == 0 ||
  570. Constructable::get_num_move_constructor_calls() == 4);
  571. // Without ever moving or copying anything else.
  572. EXPECT_EQ(0, Constructable::get_num_copy_assignment_calls());
  573. EXPECT_EQ(0, Constructable::get_num_move_assignment_calls());
  574. EXPECT_EQ(this->the_vector.begin() + 4, it);
  575. this->assert_values_in_order(this->the_vector, 6u, 1, 2, 3, 4, 16, 16);
  576. }
  577. TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) {
  578. SCOPED_TRACE("InsertRepeatedTest");
  579. this->make_sequence(this->the_vector, 10, 15);
  580. // Empty insert.
  581. EXPECT_EQ(this->the_vector.end(),
  582. this->the_vector.insert(this->the_vector.end(), 0,
  583. Constructable(42)));
  584. EXPECT_EQ(this->the_vector.begin() + 1,
  585. this->the_vector.insert(this->the_vector.begin() + 1, 0,
  586. Constructable(42)));
  587. }
  588. // Insert range.
  589. TYPED_TEST(SmallVectorTest, InsertRangeTest) {
  590. SCOPED_TRACE("InsertRangeTest");
  591. Constructable arr[3] = {Constructable(77), Constructable(77),
  592. Constructable(77)};
  593. this->make_sequence(this->the_vector, 1, 3);
  594. Constructable::reset();
  595. auto it =
  596. this->the_vector.insert(this->the_vector.begin() + 1, arr, arr + 3);
  597. // Move construct the top 3 elements into newly allocated space.
  598. // Possibly move the whole sequence into new space first.
  599. // FIXME: This is inefficient, we shouldn't move things into newly allocated
  600. // space, then move them up/around, there should only be 2 or 3 move
  601. // constructions here.
  602. EXPECT_TRUE(Constructable::get_num_move_constructor_calls() == 2 ||
  603. Constructable::get_num_move_constructor_calls() == 5);
  604. // Copy assign the lower 2 new elements into existing space.
  605. EXPECT_EQ(2, Constructable::get_num_copy_assignment_calls());
  606. // Copy construct the third element into newly allocated space.
  607. // EXPECT_EQ(1, Constructable::get_num_copy_constructor_calls());
  608. EXPECT_EQ(this->the_vector.begin() + 1, it);
  609. this->assert_values_in_order(this->the_vector, 6u, 1, 77, 77, 77, 2, 3);
  610. }
  611. TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) {
  612. SCOPED_TRACE("InsertRangeTest");
  613. Constructable arr[3] = {Constructable(77), Constructable(77),
  614. Constructable(77)};
  615. this->make_sequence(this->the_vector, 1, 3);
  616. // Insert at end.
  617. Constructable::reset();
  618. auto it = this->the_vector.insert(this->the_vector.end(), arr, arr + 3);
  619. // Copy construct the 3 elements into new space at the top.
  620. // EXPECT_EQ(3, Constructable::get_num_copy_constructor_calls());
  621. // Don't copy/move anything else.
  622. EXPECT_EQ(0, Constructable::get_num_copy_assignment_calls());
  623. // Reallocation might occur, causing all elements to be moved into the new
  624. // buffer.
  625. EXPECT_TRUE(Constructable::get_num_move_constructor_calls() == 0 ||
  626. Constructable::get_num_move_constructor_calls() == 3);
  627. EXPECT_EQ(0, Constructable::get_num_move_assignment_calls());
  628. EXPECT_EQ(this->the_vector.begin() + 3, it);
  629. this->assert_values_in_order(this->the_vector, 6u, 1, 2, 3, 77, 77, 77);
  630. }
  631. TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) {
  632. SCOPED_TRACE("InsertRangeTest");
  633. this->make_sequence(this->the_vector, 1, 3);
  634. // Empty insert.
  635. EXPECT_EQ(this->the_vector.end(),
  636. this->the_vector.insert(this->the_vector.end(),
  637. this->the_vector.begin(),
  638. this->the_vector.begin()));
  639. EXPECT_EQ(this->the_vector.begin() + 1,
  640. this->the_vector.insert(this->the_vector.begin() + 1,
  641. this->the_vector.begin(),
  642. this->the_vector.begin()));
  643. }
  644. // Comparison tests.
  645. TYPED_TEST(SmallVectorTest, ComparisonTest) {
  646. SCOPED_TRACE("ComparisonTest");
  647. this->make_sequence(this->the_vector, 1, 3);
  648. this->make_sequence(this->other_vector, 1, 3);
  649. EXPECT_TRUE(this->the_vector == this->other_vector);
  650. EXPECT_FALSE(this->the_vector != this->other_vector);
  651. this->other_vector.clear();
  652. this->make_sequence(this->other_vector, 2, 4);
  653. EXPECT_FALSE(this->the_vector == this->other_vector);
  654. EXPECT_TRUE(this->the_vector != this->other_vector);
  655. }
  656. // Constant vector tests.
  657. TYPED_TEST(SmallVectorTest, ConstVectorTest) {
  658. const TypeParam const_vector;
  659. EXPECT_EQ(0u, const_vector.size());
  660. EXPECT_TRUE(const_vector.empty());
  661. EXPECT_TRUE(const_vector.begin() == const_vector.end());
  662. }
  663. // Direct array access.
  664. TYPED_TEST(SmallVectorTest, DirectVectorTest) {
  665. EXPECT_EQ(0u, this->the_vector.size());
  666. this->the_vector.reserve(4);
  667. EXPECT_LE(4u, this->the_vector.capacity());
  668. EXPECT_EQ(0, Constructable::get_num_constructor_calls());
  669. this->the_vector.push_back(1);
  670. this->the_vector.push_back(2);
  671. this->the_vector.push_back(3);
  672. this->the_vector.push_back(4);
  673. EXPECT_EQ(4u, this->the_vector.size());
  674. EXPECT_EQ(8, Constructable::get_num_constructor_calls());
  675. EXPECT_EQ(1, this->the_vector[0].get_value());
  676. EXPECT_EQ(2, this->the_vector[1].get_value());
  677. EXPECT_EQ(3, this->the_vector[2].get_value());
  678. EXPECT_EQ(4, this->the_vector[3].get_value());
  679. }
  680. TYPED_TEST(SmallVectorTest, IteratorTest) {
  681. std::list<int> list;
  682. this->the_vector.insert(this->the_vector.end(), list.begin(), list.end());
  683. }
  684. template <typename InvalidType>
  685. class DualSmallVectorsTest;
  686. template <typename VectorT1, typename VectorT2>
  687. class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>>
  688. : public SmallVectorTestBase {
  689. protected:
  690. VectorT1 the_vector;
  691. VectorT2 other_vector;
  692. template <typename T, unsigned N>
  693. static unsigned num_builtin_elms(const SmallVector<T, N>&) {
  694. return N;
  695. }
  696. };
  697. typedef ::testing::Types<
  698. // Small mode -> Small mode.
  699. std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 4>>,
  700. // Small mode -> Big mode.
  701. std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 2>>,
  702. // Big mode -> Small mode.
  703. std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 4>>,
  704. // Big mode -> Big mode.
  705. std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 2>>>
  706. DualSmallVectorTestTypes;
  707. TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes);
  708. TYPED_TEST(DualSmallVectorsTest, MoveAssignment) {
  709. SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
  710. // Set up our vector with four elements.
  711. for (unsigned it = 0; it < 4; ++it)
  712. this->other_vector.push_back(Constructable(it));
  713. const Constructable* orig_data_ptr = this->other_vector.data();
  714. // Move-assign from the other vector.
  715. this->the_vector = std::move(
  716. static_cast<SmallVectorImpl<Constructable>&>(this->other_vector));
  717. // Make sure we have the right result.
  718. this->assert_values_in_order(this->the_vector, 4u, 0, 1, 2, 3);
  719. // Make sure the # of constructor/destructor calls line up. There
  720. // are two live objects after clearing the other vector.
  721. this->other_vector.clear();
  722. EXPECT_EQ(Constructable::get_num_constructor_calls() - 4,
  723. Constructable::get_num_destructor_calls());
  724. // If the source vector (other_vector) was in small-mode, assert that we
  725. // just
  726. // moved the data pointer over.
  727. EXPECT_TRUE(this->num_builtin_elms(this->other_vector) == 4 ||
  728. this->the_vector.data() == orig_data_ptr);
  729. // There shouldn't be any live objects any more.
  730. this->the_vector.clear();
  731. EXPECT_EQ(Constructable::get_num_constructor_calls(),
  732. Constructable::get_num_destructor_calls());
  733. // We shouldn't have copied anything in this whole process.
  734. // EXPECT_EQ(Constructable::get_num_copy_constructor_calls(), 0);
  735. }
  736. struct NotAssignable {
  737. int& x;
  738. NotAssignable(int& x) : x(x) {}
  739. };
  740. TEST(SmallVectorCustomTest, NoAssignTest) {
  741. int x = 0;
  742. SmallVector<NotAssignable, 2> vec;
  743. vec.push_back(NotAssignable(x));
  744. x = 42;
  745. EXPECT_EQ(42, vec.pop_back_val().x);
  746. }
  747. struct MovedFrom {
  748. bool has_value;
  749. MovedFrom() : has_value(true) {}
  750. MovedFrom(MovedFrom&& m) : has_value(m.has_value) { m.has_value = false; }
  751. MovedFrom& operator=(MovedFrom&& m) {
  752. has_value = m.has_value;
  753. m.has_value = false;
  754. return *this;
  755. }
  756. };
  757. TEST(SmallVectorTest, MidInsert) {
  758. SmallVector<MovedFrom, 3> v;
  759. v.push_back(MovedFrom());
  760. v.insert(v.begin(), MovedFrom());
  761. for (MovedFrom& m : v)
  762. EXPECT_TRUE(m.has_value);
  763. }
  764. enum EmplaceableArgstate {
  765. EAS_Defaulted,
  766. EAS_Arg,
  767. EAS_LValue,
  768. EAS_RValue,
  769. EAS_Failure
  770. };
  771. template <int it>
  772. struct EmplaceableArg {
  773. EmplaceableArgstate state;
  774. EmplaceableArg() : state(EAS_Defaulted) {}
  775. EmplaceableArg(EmplaceableArg&& x)
  776. : state(x.state == EAS_Arg ? EAS_RValue : EAS_Failure) {}
  777. EmplaceableArg(EmplaceableArg& x)
  778. : state(x.state == EAS_Arg ? EAS_LValue : EAS_Failure) {}
  779. explicit EmplaceableArg(bool) : state(EAS_Arg) {}
  780. private:
  781. EmplaceableArg& operator=(EmplaceableArg&&) = delete;
  782. EmplaceableArg& operator=(const EmplaceableArg&) = delete;
  783. };
  784. enum Emplaceablestate { ES_Emplaced, ES_Moved };
  785. struct Emplaceable {
  786. EmplaceableArg<0> a0;
  787. EmplaceableArg<1> a1;
  788. EmplaceableArg<2> a2;
  789. EmplaceableArg<3> a3;
  790. Emplaceablestate state;
  791. Emplaceable() : state(ES_Emplaced) {}
  792. template <class A0Ty>
  793. explicit Emplaceable(A0Ty&& a0)
  794. : a0(std::forward<A0Ty>(a0)), state(ES_Emplaced) {}
  795. template <class A0Ty, class A1Ty>
  796. Emplaceable(A0Ty&& a0, A1Ty&& a1)
  797. : a0(std::forward<A0Ty>(a0)),
  798. a1(std::forward<A1Ty>(a1)),
  799. state(ES_Emplaced) {}
  800. template <class A0Ty, class A1Ty, class A2Ty>
  801. Emplaceable(A0Ty&& a0, A1Ty&& a1, A2Ty&& a2)
  802. : a0(std::forward<A0Ty>(a0)),
  803. a1(std::forward<A1Ty>(a1)),
  804. a2(std::forward<A2Ty>(a2)),
  805. state(ES_Emplaced) {}
  806. template <class A0Ty, class A1Ty, class A2Ty, class A3Ty>
  807. Emplaceable(A0Ty&& a0, A1Ty&& a1, A2Ty&& a2, A3Ty&& a3)
  808. : a0(std::forward<A0Ty>(a0)),
  809. a1(std::forward<A1Ty>(a1)),
  810. a2(std::forward<A2Ty>(a2)),
  811. a3(std::forward<A3Ty>(a3)),
  812. state(ES_Emplaced) {}
  813. Emplaceable(Emplaceable&&) : state(ES_Moved) {}
  814. Emplaceable& operator=(Emplaceable&&) {
  815. state = ES_Moved;
  816. return *this;
  817. }
  818. private:
  819. Emplaceable(const Emplaceable&) = delete;
  820. Emplaceable& operator=(const Emplaceable&) = delete;
  821. };
  822. TEST(SmallVectorTest, EmplaceBack) {
  823. EmplaceableArg<0> a0(true);
  824. EmplaceableArg<1> a1(true);
  825. EmplaceableArg<2> a2(true);
  826. EmplaceableArg<3> a3(true);
  827. {
  828. SmallVector<Emplaceable, 3> v;
  829. v.emplace_back();
  830. EXPECT_TRUE(v.size() == 1);
  831. EXPECT_TRUE(v.back().state == ES_Emplaced);
  832. EXPECT_TRUE(v.back().a0.state == EAS_Defaulted);
  833. EXPECT_TRUE(v.back().a1.state == EAS_Defaulted);
  834. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  835. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  836. }
  837. {
  838. SmallVector<Emplaceable, 3> v;
  839. v.emplace_back(std::move(a0));
  840. EXPECT_TRUE(v.size() == 1);
  841. EXPECT_TRUE(v.back().state == ES_Emplaced);
  842. EXPECT_TRUE(v.back().a0.state == EAS_RValue);
  843. EXPECT_TRUE(v.back().a1.state == EAS_Defaulted);
  844. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  845. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  846. }
  847. {
  848. SmallVector<Emplaceable, 3> v;
  849. v.emplace_back(a0);
  850. EXPECT_TRUE(v.size() == 1);
  851. EXPECT_TRUE(v.back().state == ES_Emplaced);
  852. EXPECT_TRUE(v.back().a0.state == EAS_LValue);
  853. EXPECT_TRUE(v.back().a1.state == EAS_Defaulted);
  854. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  855. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  856. }
  857. {
  858. SmallVector<Emplaceable, 3> v;
  859. v.emplace_back(a0, a1);
  860. EXPECT_TRUE(v.size() == 1);
  861. EXPECT_TRUE(v.back().state == ES_Emplaced);
  862. EXPECT_TRUE(v.back().a0.state == EAS_LValue);
  863. EXPECT_TRUE(v.back().a1.state == EAS_LValue);
  864. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  865. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  866. }
  867. {
  868. SmallVector<Emplaceable, 3> v;
  869. v.emplace_back(std::move(a0), std::move(a1));
  870. EXPECT_TRUE(v.size() == 1);
  871. EXPECT_TRUE(v.back().state == ES_Emplaced);
  872. EXPECT_TRUE(v.back().a0.state == EAS_RValue);
  873. EXPECT_TRUE(v.back().a1.state == EAS_RValue);
  874. EXPECT_TRUE(v.back().a2.state == EAS_Defaulted);
  875. EXPECT_TRUE(v.back().a3.state == EAS_Defaulted);
  876. }
  877. {
  878. SmallVector<Emplaceable, 3> v;
  879. v.emplace_back(std::move(a0), a1, std::move(a2), a3);
  880. EXPECT_TRUE(v.size() == 1);
  881. EXPECT_TRUE(v.back().state == ES_Emplaced);
  882. EXPECT_TRUE(v.back().a0.state == EAS_RValue);
  883. EXPECT_TRUE(v.back().a1.state == EAS_LValue);
  884. EXPECT_TRUE(v.back().a2.state == EAS_RValue);
  885. EXPECT_TRUE(v.back().a3.state == EAS_LValue);
  886. }
  887. {
  888. SmallVector<int, 1> v;
  889. v.emplace_back();
  890. v.emplace_back(42);
  891. EXPECT_EQ(2U, v.size());
  892. EXPECT_EQ(0, v[0]);
  893. EXPECT_EQ(42, v[1]);
  894. }
  895. }
  896. TEST(SmallVectorTest, FindTest) {
  897. SmallVector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8};
  898. EXPECT_EQ(find(v, 3), &v[3]);
  899. EXPECT_EQ(find(v, 6), &v[6]);
  900. v[3] = 6;
  901. EXPECT_EQ(find(v, 6), &v[3]);
  902. EXPECT_EQ(find(v, 2), &v[2]);
  903. }
  904. TEST(SmallVectorTest, InitializerList) {
  905. SmallVector<int, 2> v1 = {};
  906. EXPECT_TRUE(v1.empty());
  907. v1 = {0, 0};
  908. EXPECT_TRUE(std::equal(v1.begin(), v1.end(),
  909. std::initializer_list<int>({0, 0}).begin()));
  910. v1 = {-1, -1};
  911. EXPECT_TRUE(std::equal(v1.begin(), v1.end(),
  912. std::initializer_list<int>({-1, -1}).begin()));
  913. SmallVector<int, 2> v2 = {1, 2, 3, 4};
  914. EXPECT_TRUE(std::equal(v2.begin(), v2.end(),
  915. std::initializer_list<int>({1, 2, 3, 4}).begin()));
  916. v2.assign({4});
  917. EXPECT_TRUE(std::equal(v2.begin(), v2.end(),
  918. std::initializer_list<int>({4}).begin()));
  919. v2.append({3, 2});
  920. EXPECT_TRUE(std::equal(v2.begin(), v2.end(),
  921. std::initializer_list<int>({4, 3, 2}).begin()));
  922. v2.insert(v2.begin() + 1, 5);
  923. EXPECT_TRUE(std::equal(v2.begin(), v2.end(),
  924. std::initializer_list<int>({4, 5, 3, 2}).begin()));
  925. }
  926. TEST(SmallVectorTest, PutElementWithinVectorIntoItself) {
  927. SmallVector<Constructable> vector;
  928. vector.emplace_back(0);
  929. for (size_t i = 0; i < 10; ++i) {
  930. vector.push_back(vector[0]);
  931. }
  932. vector.assign(30, vector[0]);
  933. vector.resize(90, vector[0]);
  934. vector.append(270, vector[0]);
  935. for (size_t i = 0; i < 1000; ++i) {
  936. vector.insert(&vector[0], vector[0]);
  937. }
  938. vector.insert(vector.begin(), 3000, vector[0]);
  939. }
  940. TEST(SmallVectorTest, SwapMoveOnly) {
  941. auto run = [](size_t nr0, size_t nr1, bool use_std_swap) {
  942. SmallVector<MoveOnly, 2> vec0, vec1;
  943. for (size_t i = 0; i < nr0; ++i) {
  944. vec0.emplace_back(i * 2 + 1);
  945. }
  946. for (size_t i = 0; i < nr1; ++i) {
  947. vec1.emplace_back(i * 2 + 2);
  948. }
  949. if (use_std_swap) {
  950. std::swap(vec0, vec1);
  951. } else {
  952. vec0.swap(vec1);
  953. }
  954. ASSERT_EQ(nr0, vec1.size());
  955. ASSERT_EQ(nr1, vec0.size());
  956. for (size_t i = 0; i < nr0; ++i) {
  957. ASSERT_EQ(static_cast<int>(i * 2 + 1), vec1[i].val);
  958. }
  959. for (size_t i = 0; i < nr1; ++i) {
  960. ASSERT_EQ(static_cast<int>(i * 2 + 2), vec0[i].val);
  961. }
  962. };
  963. for (int i = 0; i < 5; ++i) {
  964. for (int j = 0; j < 5; ++j) {
  965. run(i, j, 0);
  966. run(i, j, 1);
  967. }
  968. }
  969. }
  970. } // anonymous namespace
  971. // vim: syntax=cpp.doxygen foldmethod=marker foldmarker=f{{{,f}}}

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台