functional.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #include <boost/hana/assert.hpp>
  5. #include <boost/hana/config.hpp>
  6. #include <boost/hana/functional.hpp>
  7. #include <laws/base.hpp>
  8. #include <support/tracked.hpp>
  9. #include <utility>
  10. namespace hana = boost::hana;
  11. template <int i = 0>
  12. struct nonpod : Tracked {
  13. nonpod() : Tracked{i} { }
  14. };
  15. template <int i = 0>
  16. struct undefined { };
  17. struct move_only {
  18. move_only() = default;
  19. move_only(move_only&&) = default;
  20. move_only(move_only const&) = delete;
  21. };
  22. int main() {
  23. hana::test::_injection<0> f{};
  24. hana::test::_injection<1> g{};
  25. hana::test::_injection<2> h{};
  26. using hana::test::ct_eq;
  27. // always
  28. {
  29. auto z = ct_eq<0>{};
  30. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  31. hana::always(z)(), z
  32. ));
  33. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  34. hana::always(z)(undefined<1>{}), z
  35. ));
  36. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  37. hana::always(z)(undefined<1>{}, undefined<2>{}), z
  38. ));
  39. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  40. hana::always(z)(undefined<1>{}, undefined<2>{}, undefined<3>{}), z
  41. ));
  42. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  43. hana::always(z)(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}), z
  44. ));
  45. hana::always(z)(nonpod<>{});
  46. auto m = hana::always(move_only{})(undefined<1>{}); (void)m;
  47. }
  48. // apply (tested separately)
  49. {
  50. }
  51. // arg
  52. {
  53. // moveonly friendliness:
  54. move_only z = hana::arg<1>(move_only{}); (void)z;
  55. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  56. hana::arg<1>(ct_eq<1>{}),
  57. ct_eq<1>{}
  58. ));
  59. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  60. hana::arg<1>(ct_eq<1>{}, undefined<2>{}),
  61. ct_eq<1>{}
  62. ));
  63. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  64. hana::arg<1>(ct_eq<1>{}, undefined<2>{}, undefined<3>{}),
  65. ct_eq<1>{}
  66. ));
  67. hana::arg<1>(nonpod<1>{});
  68. hana::arg<1>(nonpod<1>{}, nonpod<2>{});
  69. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  70. hana::arg<2>(undefined<1>{}, ct_eq<2>{}),
  71. ct_eq<2>{}
  72. ));
  73. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  74. hana::arg<2>(undefined<1>{}, ct_eq<2>{}, undefined<3>{}),
  75. ct_eq<2>{}
  76. ));
  77. hana::arg<2>(nonpod<1>{}, nonpod<2>{});
  78. hana::arg<2>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{});
  79. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  80. hana::arg<3>(undefined<1>{}, undefined<2>{}, ct_eq<3>{}),
  81. ct_eq<3>{}
  82. ));
  83. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  84. hana::arg<3>(undefined<1>{}, undefined<2>{}, ct_eq<3>{}, undefined<4>{}),
  85. ct_eq<3>{}
  86. ));
  87. hana::arg<3>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{});
  88. hana::arg<3>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{});
  89. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  90. hana::arg<4>(undefined<1>{}, undefined<2>{}, undefined<3>{}, ct_eq<4>{}),
  91. ct_eq<4>{}
  92. ));
  93. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  94. hana::arg<4>(undefined<1>{}, undefined<2>{}, undefined<3>{}, ct_eq<4>{}, undefined<5>{}),
  95. ct_eq<4>{}
  96. ));
  97. hana::arg<4>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{});
  98. hana::arg<4>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{});
  99. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  100. hana::arg<5>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, ct_eq<5>{}),
  101. ct_eq<5>{}
  102. ));
  103. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  104. hana::arg<5>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, ct_eq<5>{}, undefined<6>{}),
  105. ct_eq<5>{}
  106. ));
  107. hana::arg<5>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{});
  108. hana::arg<5>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{}, nonpod<6>{});
  109. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  110. hana::arg<6>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, undefined<5>{}, ct_eq<6>{}),
  111. ct_eq<6>{}
  112. ));
  113. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  114. hana::arg<6>(undefined<1>{}, undefined<2>{}, undefined<3>{}, undefined<4>{}, undefined<5>{}, ct_eq<6>{}, undefined<7>{}),
  115. ct_eq<6>{}
  116. ));
  117. hana::arg<6>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{}, nonpod<6>{});
  118. hana::arg<6>(nonpod<1>{}, nonpod<2>{}, nonpod<3>{}, nonpod<4>{}, nonpod<5>{}, nonpod<6>{}, nonpod<7>{});
  119. }
  120. // compose
  121. {
  122. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  123. hana::compose(f, g)(ct_eq<0>{}),
  124. f(g(ct_eq<0>{}))
  125. ));
  126. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  127. hana::compose(f, g)(ct_eq<0>{}, ct_eq<1>{}),
  128. f(g(ct_eq<0>{}), ct_eq<1>{})
  129. ));
  130. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  131. hana::compose(f, g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
  132. f(g(ct_eq<0>{}), ct_eq<1>{}, ct_eq<2>{})
  133. ));
  134. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  135. hana::compose(f, g, h)(ct_eq<0>{}),
  136. f(g(h(ct_eq<0>{})))
  137. ));
  138. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  139. hana::compose(f, g, h)(ct_eq<0>{}, ct_eq<1>{}),
  140. f(g(h(ct_eq<0>{})), ct_eq<1>{})
  141. ));
  142. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  143. hana::compose(f, g, h)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
  144. f(g(h(ct_eq<0>{})), ct_eq<1>{}, ct_eq<2>{})
  145. ));
  146. auto h = [capture = move_only{}](int) { (void)capture; return 1; };
  147. auto i = [](int) { return 1; };
  148. hana::compose(std::move(h), i)(1);
  149. {
  150. // Compose move-only functions.
  151. auto f = [capture = move_only{}](int) { (void)capture; return 1; };
  152. auto g = [capture = move_only{}](int) { (void)capture; return 1; };
  153. auto c = hana::compose(std::move(f), std::move(g)); (void)c;
  154. }
  155. }
  156. // curry
  157. {
  158. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  159. hana::curry<0>(f)(),
  160. f()
  161. ));
  162. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  163. hana::curry<1>(f)(ct_eq<1>{}),
  164. f(ct_eq<1>{})
  165. ));
  166. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  167. hana::curry<2>(f)(ct_eq<1>{})(ct_eq<2>{}),
  168. f(ct_eq<1>{}, ct_eq<2>{})
  169. ));
  170. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  171. hana::curry<2>(f)(ct_eq<1>{}, ct_eq<2>{}),
  172. f(ct_eq<1>{}, ct_eq<2>{})
  173. ));
  174. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  175. hana::curry<3>(f)(ct_eq<1>{})(ct_eq<2>{})(ct_eq<3>{}),
  176. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  177. ));
  178. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  179. hana::curry<3>(f)(ct_eq<1>{})(ct_eq<2>{}, ct_eq<3>{}),
  180. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  181. ));
  182. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  183. hana::curry<3>(f)(ct_eq<1>{}, ct_eq<2>{})(ct_eq<3>{}),
  184. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  185. ));
  186. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  187. hana::curry<3>(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
  188. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  189. ));
  190. // Make sure curry is idempotent; this is important because it allows
  191. // currying a function in generic contexts where it is unknown whether
  192. // the function is already curried.
  193. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  194. hana::curry<0>(hana::curry<0>(f))(),
  195. f()
  196. ));
  197. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  198. hana::curry<1>(hana::curry<1>(f))(ct_eq<1>{}),
  199. f(ct_eq<1>{})
  200. ));
  201. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  202. hana::curry<2>(hana::curry<2>(f))(ct_eq<1>{})(ct_eq<2>{}),
  203. f(ct_eq<1>{}, ct_eq<2>{})
  204. ));
  205. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  206. hana::curry<2>(hana::curry<2>(f))(ct_eq<1>{}, ct_eq<2>{}),
  207. f(ct_eq<1>{}, ct_eq<2>{})
  208. ));
  209. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  210. hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{})(ct_eq<2>{})(ct_eq<3>{}),
  211. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  212. ));
  213. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  214. hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{})(ct_eq<2>{}, ct_eq<3>{}),
  215. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  216. ));
  217. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  218. hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{}, ct_eq<2>{})(ct_eq<3>{}),
  219. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  220. ));
  221. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  222. hana::curry<3>(hana::curry<3>(f))(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
  223. f(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  224. ));
  225. }
  226. // demux (tested separately)
  227. {
  228. }
  229. // fix (tested separately)
  230. {
  231. }
  232. // flip
  233. {
  234. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  235. hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}),
  236. f(ct_eq<2>{}, ct_eq<1>{})
  237. ));
  238. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  239. hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
  240. f(ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{})
  241. ));
  242. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  243. hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}),
  244. f(ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{}, ct_eq<4>{})
  245. ));
  246. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  247. hana::flip(f)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{}),
  248. f(ct_eq<2>{}, ct_eq<1>{}, ct_eq<3>{}, ct_eq<4>{}, ct_eq<5>{})
  249. ));
  250. }
  251. // id
  252. {
  253. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  254. hana::id(ct_eq<0>{}),
  255. ct_eq<0>{}
  256. ));
  257. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  258. hana::id(ct_eq<1>{}),
  259. ct_eq<1>{}
  260. ));
  261. (void)hana::id(move_only{});
  262. // make sure we don't return a dangling reference
  263. auto f = []() -> decltype(auto) { return hana::id(Tracked{1}); };
  264. auto z = f(); (void)z;
  265. }
  266. // lockstep (tested separately)
  267. {
  268. }
  269. // infix
  270. {
  271. auto g = hana::infix(f);
  272. // disregard associativity
  273. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  274. ct_eq<0>{} ^g^ ct_eq<1>{},
  275. f(ct_eq<0>{}, ct_eq<1>{})
  276. ));
  277. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  278. (ct_eq<0>{} ^g)^ ct_eq<1>{},
  279. f(ct_eq<0>{}, ct_eq<1>{})
  280. ));
  281. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  282. ct_eq<0>{} ^(g^ ct_eq<1>{}),
  283. f(ct_eq<0>{}, ct_eq<1>{})
  284. ));
  285. // left partial application
  286. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  287. (ct_eq<0>{}^g)(ct_eq<1>{}),
  288. f(ct_eq<0>{}, ct_eq<1>{})
  289. ));
  290. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  291. (ct_eq<0>{}^g)(ct_eq<1>{}, ct_eq<2>{}),
  292. f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
  293. ));
  294. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  295. (ct_eq<0>{}^g)(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
  296. f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  297. ));
  298. // right partial application
  299. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  300. (g^ct_eq<1>{})(ct_eq<0>{}),
  301. f(ct_eq<0>{}, ct_eq<1>{})
  302. ));
  303. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  304. (g^ct_eq<2>{})(ct_eq<0>{}, ct_eq<1>{}),
  305. f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
  306. ));
  307. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  308. (g^ct_eq<3>{})(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
  309. f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  310. ));
  311. // equivalence with the base function
  312. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  313. g(ct_eq<0>{}, ct_eq<1>{}),
  314. f(ct_eq<0>{}, ct_eq<1>{})
  315. ));
  316. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  317. g(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
  318. f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})
  319. ));
  320. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  321. g(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
  322. f(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{})
  323. ));
  324. }
  325. // on
  326. {
  327. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  328. hana::on(f, g)(),
  329. f()
  330. ));
  331. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  332. hana::on(f, g)(ct_eq<0>{}),
  333. f(g(ct_eq<0>{}))
  334. ));
  335. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  336. hana::on(f, g)(ct_eq<0>{}, ct_eq<1>{}),
  337. f(g(ct_eq<0>{}), g(ct_eq<1>{}))
  338. ));
  339. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  340. hana::on(f, g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
  341. f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}))
  342. ));
  343. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  344. hana::on(f, g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
  345. f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}), g(ct_eq<3>{}))
  346. ));
  347. // check the infix version
  348. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  349. (f ^hana::on^ g)(),
  350. f()
  351. ));
  352. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  353. (f ^hana::on^ g)(ct_eq<0>{}),
  354. f(g(ct_eq<0>{}))
  355. ));
  356. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  357. (f ^hana::on^ g)(ct_eq<0>{}, ct_eq<1>{}),
  358. f(g(ct_eq<0>{}), g(ct_eq<1>{}))
  359. ));
  360. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  361. (f ^hana::on^ g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}),
  362. f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}))
  363. ));
  364. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  365. (f ^hana::on^ g)(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}),
  366. f(g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{}), g(ct_eq<3>{}))
  367. ));
  368. }
  369. // overload
  370. {
  371. // 1 function
  372. {
  373. auto f = hana::overload([](int) { return ct_eq<1>{}; });
  374. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
  375. }
  376. // 2 functions
  377. {
  378. auto f = hana::overload(
  379. [](int) { return ct_eq<1>{}; },
  380. [](float) { return ct_eq<2>{}; }
  381. );
  382. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
  383. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(float{}), ct_eq<2>{}));
  384. }
  385. // 3 functions
  386. {
  387. auto f = hana::overload(
  388. [](int) { return ct_eq<1>{}; },
  389. [](float) { return ct_eq<2>{}; },
  390. static_cast<ct_eq<3>(*)(char)>([](char) { return ct_eq<3>{}; })
  391. );
  392. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
  393. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(float{}), ct_eq<2>{}));
  394. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(char{}), ct_eq<3>{}));
  395. }
  396. // 4 functions
  397. {
  398. auto f = hana::overload(
  399. [](int) { return ct_eq<1>{}; },
  400. [](float) { return ct_eq<2>{}; },
  401. static_cast<ct_eq<3>(*)(char)>([](char) { return ct_eq<3>{}; }),
  402. [](auto) { return ct_eq<4>{}; }
  403. );
  404. struct otherwise { };
  405. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(int{}), ct_eq<1>{}));
  406. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(float{}), ct_eq<2>{}));
  407. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(char{}), ct_eq<3>{}));
  408. BOOST_HANA_CONSTANT_CHECK(hana::equal(f(otherwise{}), ct_eq<4>{}));
  409. }
  410. // check move-only friendliness for bare functions
  411. {
  412. void (*g)(move_only) = [](move_only) { };
  413. hana::overload(g)(move_only{});
  414. }
  415. // check non-strict matches which require a conversion
  416. {
  417. struct convertible_to_int { operator int() const { return 1; } };
  418. auto f = [](int) { return ct_eq<0>{}; };
  419. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  420. hana::overload(f)(convertible_to_int{}),
  421. ct_eq<0>{}
  422. ));
  423. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  424. hana::overload(static_cast<ct_eq<0>(*)(int)>(f))(convertible_to_int{}),
  425. ct_eq<0>{}
  426. ));
  427. }
  428. }
  429. // partial (tested separately)
  430. {
  431. }
  432. // placeholder (tested separately)
  433. {
  434. }
  435. }