ApplyTupleTest.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /*
  2. * Copyright 2012-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. #include <iostream>
  17. #include <folly/Overload.h>
  18. #include <folly/functional/ApplyTuple.h>
  19. #include <folly/portability/GTest.h>
  20. #include <array>
  21. #include <memory>
  22. namespace {
  23. void func(int a, int b, double c) {
  24. EXPECT_EQ(a, 1);
  25. EXPECT_EQ(b, 2);
  26. EXPECT_EQ(c, 3.0);
  27. }
  28. struct Wat {
  29. void func(int a, int b, double c) {
  30. ::func(a, b, c);
  31. }
  32. double retVal(int a, double b) {
  33. return a + b;
  34. }
  35. Wat() {}
  36. Wat(Wat const&) = delete;
  37. int foo;
  38. };
  39. struct Overloaded {
  40. int func(int) {
  41. return 0;
  42. }
  43. bool func(bool) {
  44. return true;
  45. }
  46. };
  47. struct Func {
  48. int operator()() const {
  49. return 1;
  50. }
  51. };
  52. struct CopyCount {
  53. CopyCount() {}
  54. CopyCount(CopyCount const&) {
  55. std::cout << "copy count copy ctor\n";
  56. }
  57. };
  58. void anotherFunc(CopyCount const&) {}
  59. std::function<void(int, int, double)> makeFunc() {
  60. return &func;
  61. }
  62. struct GuardObjBase {
  63. GuardObjBase(GuardObjBase&&) noexcept {}
  64. GuardObjBase() {}
  65. GuardObjBase(GuardObjBase const&) = delete;
  66. GuardObjBase& operator=(GuardObjBase const&) = delete;
  67. };
  68. typedef GuardObjBase const& Guard;
  69. template <class F, class Tuple>
  70. struct GuardObj : GuardObjBase {
  71. explicit GuardObj(F&& f, Tuple&& args)
  72. : f_(std::forward<F>(f)), args_(std::forward<Tuple>(args)) {}
  73. GuardObj(GuardObj&& g) noexcept
  74. : GuardObjBase(std::move(g)),
  75. f_(std::move(g.f_)),
  76. args_(std::move(g.args_)) {}
  77. ~GuardObj() {
  78. folly::apply(f_, args_);
  79. }
  80. GuardObj(const GuardObj&) = delete;
  81. GuardObj& operator=(const GuardObj&) = delete;
  82. private:
  83. F f_;
  84. Tuple args_;
  85. };
  86. template <class F, class... Args>
  87. GuardObj<typename std::decay<F>::type, std::tuple<Args...>> guard(
  88. F&& f,
  89. Args&&... args) {
  90. return GuardObj<typename std::decay<F>::type, std::tuple<Args...>>(
  91. std::forward<F>(f), std::tuple<Args...>(std::forward<Args>(args)...));
  92. }
  93. struct Mover {
  94. Mover() {}
  95. Mover(Mover&&) noexcept {}
  96. Mover(const Mover&) = delete;
  97. Mover& operator=(const Mover&) = delete;
  98. };
  99. void move_only_func(Mover&&) {}
  100. } // namespace
  101. TEST(ApplyTuple, Test) {
  102. auto argsTuple = std::make_tuple(1, 2, 3.0);
  103. auto func2 = func;
  104. folly::apply(func2, argsTuple);
  105. folly::apply(func, argsTuple);
  106. folly::apply(func, std::make_tuple(1, 2, 3.0));
  107. folly::apply(makeFunc(), std::make_tuple(1, 2, 3.0));
  108. folly::apply(makeFunc(), argsTuple);
  109. std::unique_ptr<Wat> wat(new Wat);
  110. folly::apply(&Wat::func, std::make_tuple(wat.get(), 1, 2, 3.0));
  111. auto argsTuple2 = std::make_tuple(wat.get(), 1, 2, 3.0);
  112. folly::apply(&Wat::func, argsTuple2);
  113. EXPECT_EQ(
  114. 10.0, folly::apply(&Wat::retVal, std::make_tuple(wat.get(), 1, 9.0)));
  115. auto test = guard(func, 1, 2, 3.0);
  116. CopyCount cpy;
  117. auto test2 = guard(anotherFunc, cpy);
  118. auto test3 = guard(anotherFunc, std::cref(cpy));
  119. Overloaded ovl;
  120. EXPECT_EQ(
  121. 0,
  122. folly::apply(
  123. static_cast<int (Overloaded::*)(int)>(&Overloaded::func),
  124. std::make_tuple(&ovl, 12)));
  125. EXPECT_EQ(
  126. /* do not code-mode to EXPECT_TRUE */ true,
  127. folly::apply(
  128. static_cast<bool (Overloaded::*)(bool)>(&Overloaded::func),
  129. std::make_tuple(&ovl, false)));
  130. int x = folly::apply(std::plus<int>(), std::make_tuple(12, 12));
  131. EXPECT_EQ(24, x);
  132. Mover m;
  133. folly::apply(
  134. move_only_func, std::forward_as_tuple(std::forward<Mover>(Mover())));
  135. const auto tuple3 = std::make_tuple(1, 2, 3.0);
  136. folly::apply(func, tuple3);
  137. }
  138. TEST(ApplyTuple, Mutable) {
  139. auto argsTuple = std::make_tuple(1, 2, 3.0);
  140. folly::apply(
  141. [](int a, int b, double c) mutable { func(a, b, c); }, argsTuple);
  142. }
  143. TEST(ApplyTuple, ConstOverloads) {
  144. struct ConstOverloaded {
  145. ConstOverloaded() {}
  146. int operator()() {
  147. return 101;
  148. }
  149. int operator()() const {
  150. return 102;
  151. }
  152. };
  153. ConstOverloaded covl;
  154. // call operator()()
  155. EXPECT_EQ(folly::apply(covl, std::make_tuple()), 101);
  156. EXPECT_EQ(folly::apply(std::ref(covl), std::make_tuple()), 101);
  157. EXPECT_EQ(folly::apply(std::move(covl), std::make_tuple()), 101);
  158. // call operator()() const
  159. EXPECT_EQ(
  160. folly::apply(const_cast<ConstOverloaded const&>(covl), std::make_tuple()),
  161. 102);
  162. EXPECT_EQ(folly::apply(std::cref(covl), std::make_tuple()), 102);
  163. }
  164. TEST(ApplyTuple, RefOverloads) {
  165. struct RefOverloaded {
  166. RefOverloaded() {}
  167. int operator()() & {
  168. return 201;
  169. }
  170. int operator()() const& {
  171. return 202;
  172. }
  173. int operator()() && {
  174. return 203;
  175. }
  176. };
  177. RefOverloaded rovl;
  178. // call operator()() &
  179. EXPECT_EQ(folly::apply(rovl, std::make_tuple()), 201);
  180. EXPECT_EQ(folly::apply(std::ref(rovl), std::make_tuple()), 201);
  181. // call operator()() const &
  182. EXPECT_EQ(
  183. folly::apply(const_cast<RefOverloaded const&>(rovl), std::make_tuple()),
  184. 202);
  185. EXPECT_EQ(folly::apply(std::cref(rovl), std::make_tuple()), 202);
  186. // call operator()() &&
  187. EXPECT_EQ(folly::apply(std::move(rovl), std::make_tuple()), 203);
  188. }
  189. struct MemberFunc {
  190. int x;
  191. int getX() const {
  192. return x;
  193. }
  194. void setX(int xx) {
  195. x = xx;
  196. }
  197. };
  198. TEST(ApplyTuple, MemberFunction) {
  199. MemberFunc mf;
  200. mf.x = 123;
  201. // call getter
  202. EXPECT_EQ(folly::apply(&MemberFunc::getX, std::make_tuple(&mf)), 123);
  203. // call setter
  204. folly::apply(&MemberFunc::setX, std::make_tuple(&mf, 234));
  205. EXPECT_EQ(mf.x, 234);
  206. EXPECT_EQ(folly::apply(&MemberFunc::getX, std::make_tuple(&mf)), 234);
  207. }
  208. TEST(ApplyTuple, MemberFunctionWithRefWrapper) {
  209. MemberFunc mf;
  210. mf.x = 234;
  211. EXPECT_EQ(
  212. folly::apply(&MemberFunc::getX, std::make_tuple(std::ref(mf))), 234);
  213. }
  214. TEST(ApplyTuple, MemberFunctionWithConstPointer) {
  215. MemberFunc mf;
  216. mf.x = 234;
  217. EXPECT_EQ(
  218. folly::apply(
  219. &MemberFunc::getX,
  220. std::make_tuple(const_cast<MemberFunc const*>(&mf))),
  221. 234);
  222. }
  223. TEST(ApplyTuple, MemberFunctionWithSharedPtr) {
  224. MemberFunc mf;
  225. mf.x = 234;
  226. EXPECT_EQ(
  227. folly::apply(
  228. &MemberFunc::getX, std::make_tuple(std::make_shared<MemberFunc>(mf))),
  229. 234);
  230. }
  231. TEST(ApplyTuple, MemberFunctionWithUniquePtr) {
  232. MemberFunc mf;
  233. mf.x = 234;
  234. EXPECT_EQ(
  235. folly::apply(
  236. &MemberFunc::getX, std::make_tuple(std::make_unique<MemberFunc>(mf))),
  237. 234);
  238. }
  239. TEST(ApplyTuple, Array) {
  240. folly::apply(func, std::array<int, 3>{{1, 2, 3}});
  241. folly::apply(func, std::array<double, 3>{{1, 2, 3}});
  242. }
  243. TEST(ApplyTuple, Pair) {
  244. auto add = [](int x, int y) { return x + y; };
  245. EXPECT_EQ(folly::apply(add, std::pair<int, int>{1200, 34}), 1234);
  246. }
  247. TEST(ApplyTuple, MultipleTuples) {
  248. auto add = [](int x, int y, int z) { return x * 100 + y * 10 + z; };
  249. EXPECT_EQ(123, folly::apply(add, std::make_tuple(1, 2, 3)));
  250. EXPECT_EQ(
  251. 123,
  252. folly::apply(
  253. add, std::tuple_cat(std::make_tuple(1, 2, 3), std::make_tuple())));
  254. EXPECT_EQ(
  255. 123,
  256. folly::apply(
  257. add, std::tuple_cat(std::make_tuple(1, 2), std::make_tuple(3))));
  258. EXPECT_EQ(
  259. 123,
  260. folly::apply(
  261. add, std::tuple_cat(std::make_tuple(1), std::make_tuple(2, 3))));
  262. EXPECT_EQ(
  263. 123,
  264. folly::apply(
  265. add, std::tuple_cat(std::make_tuple(), std::make_tuple(1, 2, 3))));
  266. EXPECT_EQ(
  267. 123,
  268. folly::apply(
  269. add,
  270. std::tuple_cat(
  271. std::make_tuple(1, 2, 3), std::make_tuple(), std::make_tuple())));
  272. EXPECT_EQ(
  273. 123,
  274. folly::apply(
  275. add,
  276. std::tuple_cat(
  277. std::make_tuple(1), std::make_tuple(2), std::make_tuple(3))));
  278. EXPECT_EQ(
  279. 123,
  280. folly::apply(
  281. add,
  282. std::tuple_cat(
  283. std::make_tuple(1), std::make_tuple(), std::make_tuple(2, 3))));
  284. }
  285. TEST(ApplyTuple, UncurryCopyMove) {
  286. std::string separator = "================================\n";
  287. auto formatRow = folly::uncurry([=](std::string a, std::string b) {
  288. // capture separator by copy
  289. return separator + a + "\n" + b + "\n" + separator;
  290. });
  291. auto row = std::make_tuple("hello", "world");
  292. auto expected = separator + "hello\nworld\n" + separator;
  293. EXPECT_EQ(expected, formatRow(row));
  294. auto formatRowCopy = formatRow;
  295. EXPECT_EQ(expected, formatRowCopy(row));
  296. auto formatRowMove = std::move(formatRow);
  297. EXPECT_EQ(expected, formatRowMove(row));
  298. // capture value moved out from formatRow
  299. EXPECT_NE(expected, formatRow(row));
  300. }
  301. TEST(ApplyTuple, Uncurry) {
  302. EXPECT_EQ(42, folly::uncurry([](int x, int y) {
  303. return x * y;
  304. })(std::pair<int, int>(6, 7)));
  305. EXPECT_EQ(42, folly::uncurry([](int&& x, int&& y) {
  306. return x * y;
  307. })(std::pair<int&&, int&&>(6, 7)));
  308. EXPECT_EQ(42, folly::uncurry([](int&& x, int&& y) {
  309. return x * y;
  310. })(std::pair<int&&, int&&>(6, 7)));
  311. std::string long1 = "a long string exceeding small string size";
  312. std::string long2 = "and here is another one!";
  313. std::string expected = long1 + long2;
  314. auto cat = folly::uncurry(
  315. [](std::string a, std::string b) { return std::move(a) + std::move(b); });
  316. EXPECT_EQ(expected, cat(std::make_pair(long1, long2)));
  317. EXPECT_FALSE(long1.empty());
  318. EXPECT_FALSE(long2.empty());
  319. EXPECT_EQ(expected, cat(std::tie(long1, long2)));
  320. EXPECT_FALSE(long1.empty());
  321. EXPECT_FALSE(long2.empty());
  322. EXPECT_EQ(
  323. expected, cat(std::forward_as_tuple(std::move(long1), std::move(long2))));
  324. EXPECT_TRUE(long1.empty());
  325. EXPECT_TRUE(long2.empty());
  326. }
  327. TEST(ApplyTuple, UncurryStdFind) {
  328. std::vector<std::pair<int, int>> v{{1, 9}, {2, 8}, {3, 7}, {4, 6}, {5, 5}};
  329. EXPECT_EQ(
  330. 3, std::count_if(v.begin(), v.end(), folly::uncurry([](int a, int b) {
  331. return b % a == 0;
  332. })));
  333. }
  334. namespace {
  335. struct S {
  336. template <typename... Args>
  337. explicit S(Args&&... args) : tuple_(std::forward<Args>(args)...) {}
  338. std::tuple<int, double, std::string> tuple_;
  339. };
  340. } // namespace
  341. TEST(MakeFromTupleTest, make_from_tuple) {
  342. S expected{42, 1.0, "foobar"};
  343. // const lvalue ref
  344. auto s1 = folly::make_from_tuple<S>(expected.tuple_);
  345. EXPECT_EQ(expected.tuple_, s1.tuple_);
  346. // rvalue ref
  347. S sCopy{expected.tuple_};
  348. auto s2 = folly::make_from_tuple<S>(std::move(sCopy.tuple_));
  349. EXPECT_EQ(expected.tuple_, s2.tuple_);
  350. EXPECT_TRUE(std::get<2>(sCopy.tuple_).empty());
  351. // forward
  352. std::string str{"foobar"};
  353. auto s3 =
  354. folly::make_from_tuple<S>(std::forward_as_tuple(42, 1.0, std::move(str)));
  355. EXPECT_EQ(expected.tuple_, s3.tuple_);
  356. EXPECT_TRUE(str.empty());
  357. }
  358. TEST(MakeIndexSequenceFromTuple, Basic) {
  359. using folly::index_sequence;
  360. using folly::index_sequence_for_tuple;
  361. using OneElementTuple = std::tuple<int>;
  362. using TwoElementTuple = std::tuple<int>;
  363. EXPECT_TRUE((std::is_same<
  364. index_sequence_for_tuple<OneElementTuple>,
  365. index_sequence<0>>::value));
  366. EXPECT_TRUE((std::is_same<
  367. index_sequence_for_tuple<const OneElementTuple>,
  368. index_sequence<0>>::value));
  369. EXPECT_TRUE((std::is_same<
  370. index_sequence_for_tuple<TwoElementTuple>,
  371. index_sequence<0>>::value));
  372. EXPECT_TRUE((std::is_same<
  373. index_sequence_for_tuple<const TwoElementTuple>,
  374. index_sequence<0>>::value));
  375. }
  376. TEST(ApplyResult, Basic) {
  377. {
  378. auto f = [](auto) -> int { return {}; };
  379. EXPECT_TRUE((std::is_same<
  380. folly::apply_result_t<decltype(f), std::tuple<int>>,
  381. int>{}));
  382. }
  383. {
  384. auto f = folly::overload(
  385. [](int) {},
  386. [](double) -> double { return {}; },
  387. [](int, int) -> int { return {}; });
  388. EXPECT_TRUE((std::is_same<
  389. folly::apply_result_t<decltype(f), std::tuple<int>>,
  390. void>::value));
  391. EXPECT_TRUE((std::is_same<
  392. folly::apply_result_t<decltype(f), std::tuple<double>>,
  393. double>::value));
  394. EXPECT_TRUE((std::is_same<
  395. folly::apply_result_t<decltype(f), std::tuple<int, int>>,
  396. int>::value));
  397. }
  398. }
  399. TEST(IsApplicable, Basic) {
  400. {
  401. auto f = [] {};
  402. EXPECT_TRUE((folly::is_applicable<decltype(f), std::tuple<>>::value));
  403. EXPECT_FALSE((folly::is_applicable<decltype(f), std::tuple<int>>::value));
  404. }
  405. {
  406. auto f = folly::overload([](int) {}, [](double) -> double { return {}; });
  407. EXPECT_TRUE((folly::is_applicable<decltype(f), std::tuple<double>>::value));
  408. EXPECT_TRUE((folly::is_applicable<decltype(f), std::tuple<int>>::value));
  409. EXPECT_FALSE((folly::is_applicable<decltype(f), std::tuple<>>::value));
  410. EXPECT_FALSE(
  411. (folly::is_applicable<decltype(f), std::tuple<int, double>>::value));
  412. }
  413. }
  414. TEST(IsNothrowApplicable, Basic) {
  415. {
  416. auto f = []() noexcept {};
  417. EXPECT_TRUE((folly::is_nothrow_applicable<decltype(f), std::tuple<>>{}));
  418. EXPECT_FALSE(
  419. (folly::is_nothrow_applicable<decltype(f), std::tuple<int>>{}));
  420. }
  421. {
  422. auto f = folly::overload(
  423. [](int) noexcept {}, [](double) -> double { return {}; });
  424. EXPECT_FALSE(
  425. (folly::is_nothrow_applicable<decltype(f), std::tuple<double>>{}));
  426. EXPECT_TRUE((folly::is_nothrow_applicable<decltype(f), std::tuple<int>>{}));
  427. EXPECT_FALSE((folly::is_nothrow_applicable<decltype(f), std::tuple<>>{}));
  428. EXPECT_FALSE(
  429. (folly::is_nothrow_applicable<decltype(f), std::tuple<int, double>>::
  430. value));
  431. }
  432. }
  433. TEST(IsApplicableR, Basic) {
  434. {
  435. auto f = []() -> int { return {}; };
  436. EXPECT_TRUE((folly::is_applicable_r<double, decltype(f), std::tuple<>>{}));
  437. EXPECT_FALSE(
  438. (folly::is_applicable_r<double, decltype(f), std::tuple<int>>{}));
  439. }
  440. {
  441. auto f = folly::overload(
  442. [](int) noexcept {}, [](double) -> double { return {}; });
  443. EXPECT_TRUE(
  444. (folly::is_applicable_r<float, decltype(f), std::tuple<double>>{}));
  445. EXPECT_TRUE((folly::is_applicable_r<void, decltype(f), std::tuple<int>>{}));
  446. EXPECT_FALSE((folly::is_applicable_r<void, decltype(f), std::tuple<>>{}));
  447. EXPECT_FALSE(
  448. (folly::is_applicable_r<double, decltype(f), std::tuple<int, double>>::
  449. value));
  450. }
  451. }
  452. TEST(IsNothrowApplicableR, Basic) {
  453. {
  454. auto f = []() noexcept->int {
  455. return {};
  456. };
  457. EXPECT_TRUE(
  458. (folly::is_nothrow_applicable_r<double, decltype(f), std::tuple<>>{}));
  459. EXPECT_FALSE(
  460. (folly::
  461. is_nothrow_applicable_r<double, decltype(f), std::tuple<int>>{}));
  462. }
  463. {
  464. auto f = folly::overload(
  465. [](int) noexcept {}, [](double) -> double { return {}; });
  466. EXPECT_FALSE((
  467. folly::
  468. is_nothrow_applicable_r<float, decltype(f), std::tuple<double>>{}));
  469. EXPECT_TRUE(
  470. (folly::is_nothrow_applicable_r<void, decltype(f), std::tuple<int>>{}));
  471. EXPECT_FALSE(
  472. (folly::is_nothrow_applicable_r<void, decltype(f), std::tuple<>>{}));
  473. EXPECT_FALSE((folly::is_nothrow_applicable_r<
  474. double,
  475. decltype(f),
  476. std::tuple<int, double>>::value));
  477. }
  478. }
  479. TEST(ForwardTuple, Basic) {
  480. auto tuple = std::make_tuple(1, 2.0);
  481. EXPECT_TRUE((std::is_same<
  482. decltype(folly::forward_tuple(tuple)),
  483. std::tuple<int&, double&>>::value));
  484. EXPECT_EQ(folly::forward_tuple(tuple), tuple);
  485. EXPECT_TRUE((std::is_same<
  486. decltype(folly::forward_tuple(folly::as_const(tuple))),
  487. std::tuple<const int&, const double&>>::value));
  488. EXPECT_EQ(folly::forward_tuple(folly::as_const(tuple)), tuple);
  489. EXPECT_TRUE((std::is_same<
  490. decltype(folly::forward_tuple(std::move(tuple))),
  491. std::tuple<int&&, double&&>>::value));
  492. EXPECT_EQ(folly::forward_tuple(std::move(tuple)), tuple);
  493. EXPECT_TRUE(
  494. (std::is_same<
  495. decltype(folly::forward_tuple(std::move(folly::as_const(tuple)))),
  496. std::tuple<const int&, const double&>>::value));
  497. EXPECT_EQ(folly::forward_tuple(std::move(folly::as_const(tuple))), tuple);
  498. auto integer = 1;
  499. auto floating_point = 2.0;
  500. auto ref_tuple = std::forward_as_tuple(integer, std::move(floating_point));
  501. EXPECT_TRUE((std::is_same<
  502. decltype(folly::forward_tuple(ref_tuple)),
  503. std::tuple<int&, double&>>::value));
  504. EXPECT_TRUE((std::is_same<
  505. decltype(folly::forward_tuple(std::move(ref_tuple))),
  506. std::tuple<int&, double&&>>::value));
  507. EXPECT_TRUE((std::is_same<
  508. decltype(std::tuple_cat(
  509. folly::forward_tuple(tuple),
  510. folly::forward_tuple(std::move(tuple)))),
  511. std::tuple<int&, double&, int&&, double&&>>::value));
  512. }