PolyTest.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. /*
  2. * Copyright 2017-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
  17. #pragma message "Folly.Poly requires gcc-5 or greater"
  18. #else
  19. #include <folly/Poly.h>
  20. #include <folly/Conv.h>
  21. #include <folly/poly/Nullable.h>
  22. #include <folly/poly/Regular.h>
  23. #include <folly/portability/GTest.h>
  24. #include <array>
  25. using namespace folly;
  26. using namespace folly::poly;
  27. namespace {
  28. template <class T>
  29. struct Big_t {
  30. private:
  31. std::array<char, sizeof(Poly<ISemiRegular>) + 1> data_;
  32. T t_;
  33. public:
  34. Big_t() : data_{}, t_() {
  35. ++s_count;
  36. }
  37. explicit Big_t(T t) : data_{}, t_(t) {
  38. ++s_count;
  39. }
  40. Big_t(Big_t const& that) : data_(that.data_), t_(that.t_) {
  41. ++s_count;
  42. }
  43. ~Big_t() {
  44. --s_count;
  45. }
  46. Big_t& operator=(Big_t const&) = default;
  47. T value() const {
  48. return t_;
  49. }
  50. friend bool operator==(Big_t const& a, Big_t const& b) {
  51. return a.value() == b.value();
  52. }
  53. friend bool operator!=(Big_t const& a, Big_t const& b) {
  54. return !(a == b);
  55. }
  56. friend bool operator<(Big_t const& a, Big_t const& b) {
  57. return a.value() < b.value();
  58. }
  59. static std::ptrdiff_t s_count;
  60. };
  61. template <class T>
  62. std::ptrdiff_t Big_t<T>::s_count = 0;
  63. using Big = Big_t<int>;
  64. using BigDouble = Big_t<double>;
  65. } // namespace
  66. TEST(Poly, SemiRegular) {
  67. {
  68. // A small object, storable in-situ:
  69. Poly<ISemiRegular> p = 42;
  70. EXPECT_EQ(typeid(int), poly_type(p));
  71. EXPECT_EQ(42, poly_cast<int>(p));
  72. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  73. Poly<ISemiRegular> p2 = p;
  74. EXPECT_EQ(typeid(int), poly_type(p2));
  75. EXPECT_EQ(42, poly_cast<int>(p2));
  76. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  77. }
  78. EXPECT_EQ(0, Big::s_count);
  79. {
  80. // A big object, stored on the heap:
  81. Poly<ISemiRegular> p = Big(42);
  82. EXPECT_EQ(1, Big::s_count);
  83. EXPECT_EQ(typeid(Big), poly_type(p));
  84. EXPECT_EQ(42, poly_cast<Big>(p).value());
  85. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  86. Poly<ISemiRegular> p2 = p;
  87. EXPECT_EQ(2, Big::s_count);
  88. EXPECT_EQ(typeid(Big), poly_type(p2));
  89. EXPECT_EQ(42, poly_cast<Big>(p2).value());
  90. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  91. }
  92. EXPECT_EQ(0, Big::s_count);
  93. // four swap cases
  94. //
  95. {
  96. // A small object, storable in-situ:
  97. Poly<ISemiRegular> p = 42;
  98. EXPECT_EQ(typeid(int), poly_type(p));
  99. EXPECT_EQ(42, poly_cast<int>(p));
  100. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  101. // A small object, storable in-situ:
  102. Poly<ISemiRegular> p2 = 4.2;
  103. EXPECT_EQ(typeid(double), poly_type(p2));
  104. EXPECT_EQ(4.2, poly_cast<double>(p2));
  105. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  106. std::swap(p, p2);
  107. EXPECT_EQ(typeid(double), poly_type(p));
  108. EXPECT_EQ(4.2, poly_cast<double>(p));
  109. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  110. EXPECT_EQ(typeid(int), poly_type(p2));
  111. EXPECT_EQ(42, poly_cast<int>(p2));
  112. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  113. using std::swap;
  114. swap(p, p2);
  115. EXPECT_EQ(typeid(int), poly_type(p));
  116. EXPECT_EQ(42, poly_cast<int>(p));
  117. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  118. EXPECT_EQ(typeid(double), poly_type(p2));
  119. EXPECT_EQ(4.2, poly_cast<double>(p2));
  120. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  121. }
  122. EXPECT_EQ(0, Big::s_count);
  123. EXPECT_EQ(0, BigDouble::s_count);
  124. {
  125. // A big object, stored on the heap:
  126. Poly<ISemiRegular> p = Big(42);
  127. EXPECT_EQ(1, Big::s_count);
  128. EXPECT_EQ(typeid(Big), poly_type(p));
  129. EXPECT_EQ(42, poly_cast<Big>(p).value());
  130. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  131. // A big object, stored on the heap:
  132. Poly<ISemiRegular> p2 = BigDouble(4.2);
  133. EXPECT_EQ(1, BigDouble::s_count);
  134. EXPECT_EQ(typeid(BigDouble), poly_type(p2));
  135. EXPECT_EQ(4.2, poly_cast<BigDouble>(p2).value());
  136. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  137. std::swap(p, p2);
  138. EXPECT_EQ(1, Big::s_count);
  139. EXPECT_EQ(1, BigDouble::s_count);
  140. EXPECT_EQ(typeid(BigDouble), poly_type(p));
  141. EXPECT_EQ(4.2, poly_cast<BigDouble>(p).value());
  142. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  143. EXPECT_EQ(typeid(Big), poly_type(p2));
  144. EXPECT_EQ(42, poly_cast<Big>(p2).value());
  145. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  146. using std::swap;
  147. swap(p, p2);
  148. EXPECT_EQ(1, Big::s_count);
  149. EXPECT_EQ(1, BigDouble::s_count);
  150. EXPECT_EQ(typeid(Big), poly_type(p));
  151. EXPECT_EQ(42, poly_cast<Big>(p).value());
  152. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  153. EXPECT_EQ(typeid(BigDouble), poly_type(p2));
  154. EXPECT_EQ(4.2, poly_cast<BigDouble>(p2).value());
  155. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  156. }
  157. EXPECT_EQ(0, BigDouble::s_count);
  158. EXPECT_EQ(0, Big::s_count);
  159. EXPECT_EQ(0, Big::s_count);
  160. {
  161. // A big object, stored on the heap:
  162. Poly<ISemiRegular> p = Big(42);
  163. EXPECT_EQ(1, Big::s_count);
  164. EXPECT_EQ(typeid(Big), poly_type(p));
  165. EXPECT_EQ(42, poly_cast<Big>(p).value());
  166. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  167. // A small object, storable in-situ:
  168. Poly<ISemiRegular> p2 = 4.2;
  169. EXPECT_EQ(typeid(double), poly_type(p2));
  170. EXPECT_EQ(4.2, poly_cast<double>(p2));
  171. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  172. std::swap(p, p2);
  173. EXPECT_EQ(1, Big::s_count);
  174. EXPECT_EQ(typeid(double), poly_type(p));
  175. EXPECT_EQ(4.2, poly_cast<double>(p));
  176. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  177. EXPECT_EQ(typeid(Big), poly_type(p2));
  178. EXPECT_EQ(42, poly_cast<Big>(p2).value());
  179. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  180. using std::swap;
  181. swap(p, p2);
  182. EXPECT_EQ(1, Big::s_count);
  183. EXPECT_EQ(typeid(Big), poly_type(p));
  184. EXPECT_EQ(42, poly_cast<Big>(p).value());
  185. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  186. EXPECT_EQ(typeid(double), poly_type(p2));
  187. EXPECT_EQ(4.2, poly_cast<double>(p2));
  188. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  189. }
  190. EXPECT_EQ(0, Big::s_count);
  191. EXPECT_EQ(0, BigDouble::s_count);
  192. {
  193. // A small object, storable in-situ:
  194. Poly<ISemiRegular> p = 42;
  195. EXPECT_EQ(typeid(int), poly_type(p));
  196. EXPECT_EQ(42, poly_cast<int>(p));
  197. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  198. // A big object, stored on the heap:
  199. Poly<ISemiRegular> p2 = BigDouble(4.2);
  200. EXPECT_EQ(1, BigDouble::s_count);
  201. EXPECT_EQ(typeid(BigDouble), poly_type(p2));
  202. EXPECT_EQ(4.2, poly_cast<BigDouble>(p2).value());
  203. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  204. std::swap(p, p2);
  205. EXPECT_EQ(1, BigDouble::s_count);
  206. EXPECT_EQ(typeid(BigDouble), poly_type(p));
  207. EXPECT_EQ(4.2, poly_cast<BigDouble>(p).value());
  208. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  209. EXPECT_EQ(typeid(int), poly_type(p2));
  210. EXPECT_EQ(42, poly_cast<int>(p2));
  211. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  212. using std::swap;
  213. swap(p, p2);
  214. EXPECT_EQ(1, BigDouble::s_count);
  215. EXPECT_EQ(typeid(int), poly_type(p));
  216. EXPECT_EQ(42, poly_cast<int>(p));
  217. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  218. EXPECT_EQ(typeid(BigDouble), poly_type(p2));
  219. EXPECT_EQ(4.2, poly_cast<BigDouble>(p2).value());
  220. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  221. }
  222. EXPECT_EQ(0, BigDouble::s_count);
  223. }
  224. TEST(Poly, EqualityComparable) {
  225. {
  226. Poly<IEqualityComparable> p = 42;
  227. Poly<IEqualityComparable> q = 42;
  228. EXPECT_TRUE(p == q);
  229. EXPECT_TRUE(q == p);
  230. EXPECT_FALSE(p != q);
  231. EXPECT_FALSE(q != p);
  232. p = 43;
  233. EXPECT_FALSE(p == q);
  234. EXPECT_FALSE(q == p);
  235. EXPECT_TRUE(p != q);
  236. EXPECT_TRUE(q != p);
  237. }
  238. {
  239. // empty not equal
  240. Poly<IEqualityComparable> p;
  241. Poly<IEqualityComparable> q = 42;
  242. EXPECT_FALSE(p == q);
  243. EXPECT_FALSE(q == p);
  244. }
  245. {
  246. // empty equal
  247. Poly<IEqualityComparable> p;
  248. Poly<IEqualityComparable> q;
  249. EXPECT_TRUE(p == q);
  250. EXPECT_TRUE(q == p);
  251. }
  252. {
  253. // mismatched types throws
  254. Poly<IEqualityComparable> p = 4.2;
  255. Poly<IEqualityComparable> q = 42;
  256. EXPECT_THROW((void)(q == p), BadPolyCast);
  257. }
  258. }
  259. TEST(Poly, StrictlyOrderable) {
  260. {
  261. // A small object, storable in-situ:
  262. Poly<IStrictlyOrderable> p = 42;
  263. Poly<IStrictlyOrderable> q = 43;
  264. EXPECT_TRUE(p < q);
  265. EXPECT_TRUE(p <= q);
  266. EXPECT_FALSE(p > q);
  267. EXPECT_FALSE(p >= q);
  268. EXPECT_TRUE(q > p);
  269. EXPECT_TRUE(q >= p);
  270. EXPECT_FALSE(q < p);
  271. EXPECT_FALSE(q <= p);
  272. }
  273. {
  274. // A big object, stored on the heap:
  275. Poly<IStrictlyOrderable> p = Big(42);
  276. Poly<IStrictlyOrderable> q = Big(43);
  277. EXPECT_TRUE(p < q);
  278. }
  279. {
  280. // if equal, no one is bigger
  281. Poly<IStrictlyOrderable> p = 42;
  282. Poly<IStrictlyOrderable> q = 42;
  283. EXPECT_FALSE(p < q);
  284. EXPECT_TRUE(p <= q);
  285. EXPECT_FALSE(p > q);
  286. EXPECT_TRUE(p >= q);
  287. EXPECT_FALSE(q < p);
  288. EXPECT_TRUE(q <= p);
  289. EXPECT_FALSE(q > p);
  290. EXPECT_TRUE(q >= p);
  291. }
  292. {
  293. // empty is always smaller
  294. Poly<IStrictlyOrderable> p;
  295. Poly<IStrictlyOrderable> q = 42;
  296. EXPECT_TRUE(p < q);
  297. EXPECT_FALSE(q < p);
  298. }
  299. {
  300. // mismatched types throws
  301. Poly<IStrictlyOrderable> p = 4.2;
  302. Poly<IStrictlyOrderable> q = 42;
  303. EXPECT_THROW((void)(p < q), BadPolyCast);
  304. EXPECT_THROW((void)(q < p), BadPolyCast);
  305. }
  306. }
  307. TEST(Poly, SemiRegularReference) {
  308. int i = 42;
  309. Poly<ISemiRegular&> p = i;
  310. EXPECT_EQ(42, i);
  311. EXPECT_EQ(typeid(int), poly_type(p));
  312. EXPECT_EQ(42, poly_cast<int>(p));
  313. EXPECT_EQ(&i, &poly_cast<int>(p));
  314. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  315. Poly<ISemiRegular&> p2 = p;
  316. EXPECT_EQ(typeid(int), poly_type(p2));
  317. EXPECT_EQ(42, poly_cast<int>(p2));
  318. EXPECT_EQ(&i, &poly_cast<int>(p2));
  319. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  320. std::swap(p, p2);
  321. EXPECT_EQ(typeid(int), poly_type(p2));
  322. EXPECT_EQ(42, poly_cast<int>(p2));
  323. EXPECT_EQ(&i, &poly_cast<int>(p2));
  324. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  325. using std::swap;
  326. swap(p, p2);
  327. EXPECT_EQ(typeid(int), poly_type(p2));
  328. EXPECT_EQ(42, poly_cast<int>(p2));
  329. EXPECT_EQ(&i, &poly_cast<int>(p2));
  330. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  331. // Can't default-initialize reference-like Poly's:
  332. static_assert(!std::is_default_constructible<Poly<ISemiRegular&>>::value, "");
  333. }
  334. TEST(Poly, Conversions) {
  335. int i = 42;
  336. Poly<ISemiRegular> p1 = i;
  337. Poly<ISemiRegular&> p2 = p1;
  338. EXPECT_EQ(&poly_cast<int>(p1), &poly_cast<int>(p2));
  339. Poly<ISemiRegular const&> p3 = p1;
  340. Poly<ISemiRegular const&> p4 = p2;
  341. EXPECT_EQ(&poly_cast<int>(p3), &poly_cast<int>(p1));
  342. EXPECT_EQ(&poly_cast<int>(p4), &poly_cast<int>(p1));
  343. static_assert(
  344. !std::is_constructible<Poly<ISemiRegular&>, Poly<ISemiRegular const&>&>::
  345. value,
  346. "");
  347. static_assert(
  348. !std::is_constructible<Poly<ISemiRegular>, Poly<ISemiRegular const&>&>::
  349. value,
  350. "");
  351. }
  352. TEST(Poly, EqualityComparableReference) {
  353. int i = 42;
  354. int j = 42;
  355. Poly<IEqualityComparable&> p1 = i;
  356. Poly<IEqualityComparable&> p2 = j;
  357. EXPECT_EQ(&i, &poly_cast<int>(p1));
  358. EXPECT_EQ(&j, &poly_cast<int>(p2));
  359. EXPECT_TRUE(p1 == p2);
  360. EXPECT_FALSE(p1 != p2);
  361. j = 43;
  362. EXPECT_FALSE(p1 == p2);
  363. EXPECT_TRUE(p1 != p2);
  364. EXPECT_EQ(42, poly_cast<int>(p1));
  365. EXPECT_EQ(43, poly_cast<int>(p2));
  366. }
  367. namespace {
  368. struct Foo {
  369. template <class Base>
  370. struct Interface : Base {
  371. void foo(int& i) {
  372. folly::poly_call<0>(*this, i);
  373. }
  374. };
  375. template <class T>
  376. using Members = FOLLY_POLY_MEMBERS(&T::foo);
  377. };
  378. struct foo_ {
  379. foo_() = default;
  380. explicit foo_(int i) : j_(i) {}
  381. void foo(int& i) {
  382. i += j_;
  383. }
  384. private:
  385. int j_ = 0;
  386. };
  387. } // namespace
  388. TEST(Poly, Singular) {
  389. Poly<Foo> p = foo_{42};
  390. int i = 1;
  391. p.foo(i);
  392. EXPECT_EQ(43, i);
  393. EXPECT_EQ(typeid(foo_), poly_type(p));
  394. }
  395. namespace {
  396. struct FooBar : PolyExtends<Foo> {
  397. template <class Base>
  398. struct Interface : Base {
  399. std::string bar(int i) const {
  400. return folly::poly_call<0>(*this, i);
  401. }
  402. };
  403. template <class T>
  404. using Members = FOLLY_POLY_MEMBERS(&T::bar);
  405. };
  406. struct foo_bar {
  407. foo_bar() = default;
  408. explicit foo_bar(int i) : j_(i) {}
  409. void foo(int& i) {
  410. i += j_;
  411. }
  412. std::string bar(int i) const {
  413. i += j_;
  414. return folly::to<std::string>(i);
  415. }
  416. private:
  417. int j_ = 0;
  418. };
  419. } // namespace
  420. TEST(Poly, SingleInheritance) {
  421. Poly<FooBar> p = foo_bar{42};
  422. int i = 1;
  423. p.foo(i);
  424. EXPECT_EQ(43, i);
  425. EXPECT_EQ("43", p.bar(1));
  426. EXPECT_EQ(typeid(foo_bar), poly_type(p));
  427. Poly<Foo> q = p; // OK, conversion works.
  428. q.foo(i);
  429. EXPECT_EQ(85, i);
  430. Poly<Foo&> r = p;
  431. r->foo(i);
  432. EXPECT_EQ(127, i);
  433. const_cast<Poly<Foo&> const&>(r)->foo(i);
  434. EXPECT_EQ(169, i);
  435. Poly<FooBar const&> cr = p;
  436. // cr->foo(i); // ERROR: calls a non-const member through a const reference
  437. cr->bar(i); // OK
  438. }
  439. namespace {
  440. struct Baz {
  441. template <class Base>
  442. struct Interface : Base {
  443. std::string baz(int i, int j) const {
  444. return folly::poly_call<0>(*this, i, j);
  445. }
  446. };
  447. template <class T>
  448. using Members = FOLLY_POLY_MEMBERS(&T::baz);
  449. };
  450. struct FooBarBazFizz : PolyExtends<FooBar, Baz> {
  451. template <class Base>
  452. struct Interface : Base {
  453. std::string fizz() const {
  454. return folly::poly_call<0>(*this);
  455. }
  456. };
  457. template <class T>
  458. using Members = FOLLY_POLY_MEMBERS(&T::fizz);
  459. };
  460. struct foo_bar_baz_fizz {
  461. foo_bar_baz_fizz() = default;
  462. explicit foo_bar_baz_fizz(int i) : j_(i) {}
  463. void foo(int& i) {
  464. i += j_;
  465. }
  466. std::string bar(int i) const {
  467. return folly::to<std::string>(i + j_);
  468. }
  469. std::string baz(int i, int j) const {
  470. return folly::to<std::string>(i + j);
  471. }
  472. std::string fizz() const {
  473. return "fizz";
  474. }
  475. private:
  476. int j_ = 0;
  477. };
  478. } // namespace
  479. TEST(Poly, MultipleInheritance) {
  480. Poly<FooBarBazFizz> p = foo_bar_baz_fizz{42};
  481. int i = 1;
  482. p.foo(i);
  483. EXPECT_EQ(43, i);
  484. EXPECT_EQ("43", p.bar(1));
  485. EXPECT_EQ("3", p.baz(1, 2));
  486. EXPECT_EQ("fizz", p.fizz());
  487. EXPECT_EQ(typeid(foo_bar_baz_fizz), poly_type(p));
  488. }
  489. namespace {
  490. struct Property {
  491. template <class Base>
  492. struct Interface : Base {
  493. int prop() const {
  494. return folly::poly_call<0>(*this);
  495. }
  496. void prop(int i) {
  497. folly::poly_call<1>(*this, i);
  498. }
  499. };
  500. template <class T>
  501. using Members = FOLLY_POLY_MEMBERS(
  502. FOLLY_POLY_MEMBER(int() const, &T::prop),
  503. FOLLY_POLY_MEMBER(void(int), &T::prop));
  504. };
  505. struct has_property {
  506. has_property() = default;
  507. explicit has_property(int i) : j(i) {}
  508. int prop() const {
  509. return j;
  510. }
  511. void prop(int i) {
  512. j = i;
  513. }
  514. private:
  515. int j = 0;
  516. };
  517. } // namespace
  518. TEST(Poly, OverloadedMembers) {
  519. Poly<Property> p = has_property{42};
  520. EXPECT_EQ(typeid(has_property), poly_type(p));
  521. EXPECT_EQ(42, p.prop());
  522. p.prop(68);
  523. EXPECT_EQ(68, p.prop());
  524. }
  525. TEST(Poly, NullablePointer) {
  526. Poly<INullablePointer> p = nullptr;
  527. Poly<INullablePointer> q{};
  528. EXPECT_EQ(typeid(void), poly_type(p));
  529. EXPECT_TRUE(poly_empty(p));
  530. EXPECT_TRUE(p == q);
  531. EXPECT_FALSE(p != q);
  532. EXPECT_TRUE(p == nullptr);
  533. EXPECT_TRUE(nullptr == p);
  534. EXPECT_FALSE(p != nullptr);
  535. EXPECT_FALSE(nullptr != p);
  536. // No null references ever.
  537. Poly<INullablePointer> r = 42;
  538. Poly<INullablePointer&> s = r;
  539. static_assert(!poly_empty(s), "");
  540. EXPECT_THROW(Poly<INullablePointer&> r_(q), BadPolyAccess);
  541. }
  542. namespace {
  543. struct MoveOnly_ {
  544. MoveOnly_() = default;
  545. MoveOnly_(MoveOnly_&&) = default;
  546. MoveOnly_(MoveOnly_ const&) = delete;
  547. MoveOnly_& operator=(MoveOnly_&&) = default;
  548. MoveOnly_& operator=(MoveOnly_ const&) = delete;
  549. };
  550. } // namespace
  551. TEST(Poly, Move) {
  552. {
  553. int i = 42;
  554. Poly<IMoveOnly&> p = i;
  555. static_assert(
  556. !std::is_convertible<Poly<IMoveOnly&>, Poly<IMoveOnly&&>>::value, "");
  557. auto q = poly_move(p);
  558. static_assert(std::is_same<decltype(q), Poly<IMoveOnly&&>>::value, "");
  559. EXPECT_EQ(&poly_cast<int>(p), &poly_cast<int>(q));
  560. }
  561. {
  562. int i = 42;
  563. Poly<ISemiRegular const&> p = i;
  564. auto q = poly_move(p);
  565. static_assert(
  566. std::is_same<decltype(q), Poly<ISemiRegular const&>>::value, "");
  567. EXPECT_EQ(&poly_cast<int>(p), &poly_cast<int>(q));
  568. }
  569. {
  570. Poly<IMoveOnly> p = MoveOnly_{};
  571. static_assert(!std::is_copy_constructible<Poly<IMoveOnly>>::value, "");
  572. auto q = poly_move(p);
  573. static_assert(std::is_same<decltype(q), Poly<IMoveOnly>>::value, "");
  574. }
  575. }
  576. TEST(Poly, RValueRef) {
  577. int i = 42;
  578. Poly<ISemiRegular&&> p = std::move(i);
  579. static_assert(std::is_same<decltype(poly_cast<int>(p)), int&>::value, "");
  580. EXPECT_EQ(&i, &poly_cast<int>(p));
  581. }
  582. namespace {
  583. template <class Fun>
  584. struct IFunction;
  585. template <class R, class... As>
  586. struct IFunction<R(As...)> {
  587. template <class Base>
  588. struct Interface : Base {
  589. R operator()(As... as) const {
  590. return static_cast<R>(
  591. folly::poly_call<0>(*this, std::forward<As>(as)...));
  592. }
  593. };
  594. template <class T>
  595. using Members =
  596. FOLLY_POLY_MEMBERS(FOLLY_POLY_MEMBER(R(As...) const, &T::operator()));
  597. };
  598. template <class Fun>
  599. using Function = Poly<IFunction<Fun>>;
  600. } // namespace
  601. TEST(Poly, Function) {
  602. Function<int(int, int)> fun = std::plus<int>{};
  603. EXPECT_EQ(42, fun(22, 20));
  604. fun = std::multiplies<int>{};
  605. EXPECT_EQ(22 * 20, fun(22, 20));
  606. }
  607. namespace {
  608. // This multiply extends IEqualityComparable
  609. struct IDiamond : PolyExtends<IRegular, INullablePointer> {};
  610. } // namespace
  611. TEST(Poly, DiamondInheritance) {
  612. {
  613. // A small object, storable in-situ:
  614. Poly<IDiamond> p = 42;
  615. EXPECT_EQ(typeid(int), poly_type(p));
  616. EXPECT_EQ(42, poly_cast<int>(p));
  617. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  618. Poly<IDiamond> p2 = p;
  619. EXPECT_EQ(typeid(int), poly_type(p2));
  620. EXPECT_EQ(42, poly_cast<int>(p2));
  621. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  622. Poly<IEqualityComparable&> eq = p;
  623. EXPECT_EQ(&poly_cast<int>(p), &poly_cast<int>(eq));
  624. }
  625. EXPECT_EQ(0, Big::s_count);
  626. {
  627. // A big object, stored on the heap:
  628. Poly<IDiamond> p = Big(42);
  629. EXPECT_EQ(1, Big::s_count);
  630. EXPECT_EQ(typeid(Big), poly_type(p));
  631. EXPECT_EQ(42, poly_cast<Big>(p).value());
  632. EXPECT_THROW(poly_cast<short>(p), BadPolyCast);
  633. Poly<IDiamond> p2 = p;
  634. EXPECT_EQ(2, Big::s_count);
  635. EXPECT_EQ(typeid(Big), poly_type(p2));
  636. EXPECT_EQ(42, poly_cast<Big>(p2).value());
  637. EXPECT_THROW(poly_cast<short>(p2), BadPolyCast);
  638. Poly<IEqualityComparable&> eq = p;
  639. EXPECT_EQ(&poly_cast<Big>(p), &poly_cast<Big>(eq));
  640. }
  641. EXPECT_EQ(0, Big::s_count);
  642. }
  643. namespace {
  644. struct Struct {
  645. int property() const {
  646. return 42;
  647. }
  648. void property(int) {}
  649. };
  650. struct Struct2 : Struct {
  651. int meow() {
  652. return 42;
  653. }
  654. int purr() {
  655. return 1;
  656. }
  657. int purr() const {
  658. return 2;
  659. }
  660. };
  661. int property(Struct const&) {
  662. return 42;
  663. }
  664. void property(Struct&, int) {}
  665. int meow(Struct2&) {
  666. return 42;
  667. }
  668. int purr(Struct2&) {
  669. return 1;
  670. }
  671. int purr(Struct2 const&) {
  672. return 2;
  673. }
  674. } // namespace
  675. TEST(Poly, Sig) {
  676. {
  677. auto m0 = folly::sig<int() const>(&Struct::property);
  678. EXPECT_EQ(static_cast<int (Struct::*)() const>(&Struct::property), m0);
  679. auto m1 = folly::sig<int()>(&Struct::property);
  680. EXPECT_EQ(static_cast<int (Struct::*)() const>(&Struct::property), m1);
  681. auto m2 = folly::sig<int() const>(&Struct2::property);
  682. EXPECT_EQ(static_cast<int (Struct2::*)() const>(&Struct2::property), m2);
  683. auto m3 = folly::sig<int()>(&Struct2::property);
  684. EXPECT_EQ(static_cast<int (Struct2::*)() const>(&Struct2::property), m3);
  685. auto m4 = folly::sig<long()>(&Struct2::meow);
  686. EXPECT_EQ(&Struct2::meow, m4);
  687. auto m5 = folly::sig<int()>(&Struct2::purr);
  688. EXPECT_EQ(static_cast<int (Struct2::*)()>(&Struct2::purr), m5);
  689. auto m6 = folly::sig<int() const>(&Struct2::purr);
  690. EXPECT_EQ(static_cast<int (Struct2::*)() const>(&Struct2::purr), m6);
  691. }
  692. {
  693. auto m0 = folly::sig<int(Struct const&)>(&::property);
  694. EXPECT_EQ(static_cast<int (*)(Struct const&)>(&::property), m0);
  695. auto m1 = folly::sig<int(Struct&)>(&::property);
  696. EXPECT_EQ(static_cast<int (*)(Struct const&)>(&::property), m1);
  697. auto m2 = folly::sig<long(Struct2&)>(&::meow);
  698. EXPECT_EQ(&::meow, m2);
  699. auto m3 = folly::sig<int(Struct2&)>(&::purr);
  700. EXPECT_EQ(static_cast<int (*)(Struct2&)>(&::purr), m3);
  701. auto m4 = folly::sig<int(Struct2 const&)>(&::purr);
  702. EXPECT_EQ(static_cast<int (*)(Struct2 const&)>(&::purr), m4);
  703. }
  704. }
  705. namespace {
  706. struct IAddable {
  707. template <class Base>
  708. struct Interface : Base {
  709. friend PolySelf<Base, PolyDecay> operator+(
  710. PolySelf<Base> const& a,
  711. PolySelf<Base> const& b) {
  712. return folly::poly_call<0, IAddable>(a, b);
  713. }
  714. };
  715. template <class T>
  716. static auto plus_(T const& a, T const& b) -> decltype(a + b) {
  717. return a + b;
  718. }
  719. template <class T>
  720. using Members = FOLLY_POLY_MEMBERS(&plus_<std::decay_t<T>>);
  721. };
  722. } // namespace
  723. TEST(Poly, Addable) {
  724. Poly<IAddable> a = 2, b = 3;
  725. Poly<IAddable> c = a + b;
  726. EXPECT_EQ(typeid(int), poly_type(c));
  727. EXPECT_EQ(5, poly_cast<int>(c));
  728. Poly<IAddable const&> aref = a, bref = b;
  729. auto cc = aref + bref;
  730. static_assert(std::is_same<decltype(cc), Poly<IAddable>>::value, "");
  731. EXPECT_EQ(typeid(int), poly_type(cc));
  732. EXPECT_EQ(5, poly_cast<int>(cc));
  733. b = 4;
  734. EXPECT_EQ(5, poly_cast<int>(cc));
  735. cc = aref + bref;
  736. EXPECT_EQ(6, poly_cast<int>(cc));
  737. }
  738. namespace {
  739. struct IFrobnicator {
  740. template <class Base>
  741. struct Interface : Base {
  742. void frobnicate(folly::Poly<folly::poly::IRegular&> x) {
  743. folly::poly_call<0>(*this, x);
  744. }
  745. };
  746. template <class T>
  747. using Members = FOLLY_POLY_MEMBERS(&T::frobnicate);
  748. };
  749. using Frobnicator = folly::Poly<IFrobnicator>;
  750. struct my_frobnicator {
  751. void frobnicate(folly::Poly<folly::poly::IRegular&>) {
  752. // no-op
  753. }
  754. };
  755. } // namespace
  756. TEST(Poly, PolyRefAsArg) {
  757. folly::Poly<folly::poly::IRegular> x = 42;
  758. Frobnicator frob = my_frobnicator{};
  759. // should not throw:
  760. frob.frobnicate(x);
  761. // should not throw:
  762. frob.frobnicate(folly::Poly<folly::poly::IRegular&>(x));
  763. }
  764. #endif