xoptional.hpp 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTL_OPTIONAL_HPP
  10. #define XTL_OPTIONAL_HPP
  11. #include <cmath>
  12. #include <ostream>
  13. #include <type_traits>
  14. #include <utility>
  15. #ifdef __CLING__
  16. #include <nlohmann/json.hpp>
  17. #endif
  18. #include "xoptional_meta.hpp"
  19. #include "xclosure.hpp"
  20. #include "xfunctional.hpp"
  21. #include "xmeta_utils.hpp"
  22. #include "xtl_config.hpp"
  23. #include "xtype_traits.hpp"
  24. namespace xtl
  25. {
  26. template <class T, class B>
  27. auto optional(T&& t, B&& b) noexcept;
  28. /************************
  29. * optional declaration *
  30. ************************/
  31. /**
  32. * @class xoptional
  33. * @brief Optional value handler.
  34. *
  35. * The xoptional is an optional proxy. It holds a value (or a reference on a value) and a flag (or reference on a flag)
  36. * indicating whether the element should be considered missing.
  37. *
  38. * xoptional is different from std::optional
  39. *
  40. * - no `operator->()` that returns a pointer.
  41. * - no `operator*()` that returns a value.
  42. *
  43. * The only way to access the underlying value and flag is with the `value` and `value_or` methods.
  44. *
  45. * - no explicit convertion to bool. This may lead to confusion when the underlying value type is boolean too.
  46. *
  47. * @tparam CT Closure type for the value.
  48. * @tparam CB Closure type for the missing flag. A falsy flag means that the value is missing.
  49. *
  50. * \ref xoptional is used both as a value type (with CT and CB being value types) and reference type for containers
  51. * with CT and CB being reference types. In other words, it serves as a reference proxy.
  52. *
  53. */
  54. template <class CT, class CB>
  55. class xoptional
  56. {
  57. public:
  58. using self_type = xoptional<CT, CB>;
  59. using value_closure = CT;
  60. using flag_closure = CB;
  61. using value_type = std::decay_t<CT>;
  62. using flag_type = std::decay_t<CB>;
  63. // Constructors
  64. inline xoptional()
  65. : m_value(), m_flag(false)
  66. {
  67. }
  68. template <class T,
  69. std::enable_if_t<
  70. conjunction<
  71. negation<std::is_same<xoptional<CT, CB>, std::decay_t<T>>>,
  72. std::is_constructible<CT, T&&>,
  73. std::is_convertible<T&&, CT>
  74. >::value,
  75. bool
  76. > = true>
  77. inline constexpr xoptional(T&& rhs)
  78. : m_value(std::forward<T>(rhs)), m_flag(true)
  79. {
  80. }
  81. template <class T,
  82. std::enable_if_t<
  83. conjunction<
  84. negation<std::is_same<xoptional<CT, CB>, std::decay_t<T>>>,
  85. std::is_constructible<CT, T&&>,
  86. negation<std::is_convertible<T&&, CT>>
  87. >::value,
  88. bool
  89. > = false>
  90. inline explicit constexpr xoptional(T&& value)
  91. : m_value(std::forward<T>(value)), m_flag(true)
  92. {
  93. }
  94. template <class CTO, class CBO,
  95. std::enable_if_t<
  96. conjunction<
  97. negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
  98. std::is_constructible<CT, std::add_lvalue_reference_t<std::add_const_t<CTO>>>,
  99. std::is_constructible<CB, std::add_lvalue_reference_t<std::add_const_t<CBO>>>,
  100. conjunction<
  101. std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CTO>>, CT>,
  102. std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CBO>>, CB>
  103. >,
  104. negation<detail::converts_from_xoptional<CT, CTO, CBO>>
  105. >::value,
  106. bool
  107. > = true>
  108. inline constexpr xoptional(const xoptional<CTO, CBO>& rhs)
  109. : m_value(rhs.value()), m_flag(rhs.has_value())
  110. {
  111. }
  112. template <class CTO, class CBO,
  113. std::enable_if_t<
  114. conjunction<
  115. negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
  116. std::is_constructible<CT, std::add_lvalue_reference_t<std::add_const_t<CTO>>>,
  117. std::is_constructible<CB, std::add_lvalue_reference_t<std::add_const_t<CBO>>>,
  118. disjunction<
  119. negation<std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CTO>>, CT>>,
  120. negation<std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CBO>>, CB>>
  121. >,
  122. negation<detail::converts_from_xoptional<CT, CTO, CBO>>
  123. >::value,
  124. bool
  125. > = false>
  126. inline explicit constexpr xoptional(const xoptional<CTO, CBO>& rhs)
  127. : m_value(rhs.value()), m_flag(rhs.has_value())
  128. {
  129. }
  130. template <class CTO, class CBO,
  131. std::enable_if_t<
  132. conjunction<
  133. negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
  134. std::is_constructible<CT, std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>>,
  135. std::is_constructible<CB, std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>>,
  136. conjunction<
  137. std::is_convertible<std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>, CT>,
  138. std::is_convertible<std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>, CB>
  139. >,
  140. negation<detail::converts_from_xoptional<CT, CTO, CBO>>
  141. >::value,
  142. bool
  143. > = true>
  144. inline constexpr xoptional(xoptional<CTO, CBO>&& rhs)
  145. : m_value(std::move(rhs).value()), m_flag(std::move(rhs).has_value())
  146. {
  147. }
  148. template <class CTO, class CBO,
  149. std::enable_if_t<
  150. conjunction<
  151. negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
  152. std::is_constructible<CT, std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>>,
  153. std::is_constructible<CB, std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>>,
  154. disjunction<
  155. negation<std::is_convertible<std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>, CT>>,
  156. negation<std::is_convertible<std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>, CB>>
  157. >,
  158. negation<detail::converts_from_xoptional<CT, CTO, CBO>>
  159. >::value,
  160. bool
  161. > = false>
  162. inline explicit constexpr xoptional(xoptional<CTO, CBO>&& rhs)
  163. : m_value(std::move(rhs).value()), m_flag(std::move(rhs).has_value())
  164. {
  165. }
  166. xoptional(value_type&&, flag_type&&);
  167. xoptional(std::add_lvalue_reference_t<CT>, std::add_lvalue_reference_t<CB>);
  168. xoptional(value_type&&, std::add_lvalue_reference_t<CB>);
  169. xoptional(std::add_lvalue_reference_t<CT>, flag_type&&);
  170. // Assignment
  171. template <class T>
  172. std::enable_if_t<
  173. conjunction<
  174. negation<std::is_same<xoptional<CT, CB>, std::decay_t<T>>>,
  175. std::is_assignable<std::add_lvalue_reference_t<CT>, T>
  176. >::value,
  177. xoptional&>
  178. inline operator=(T&& rhs)
  179. {
  180. m_value = std::forward<T>(rhs);
  181. m_flag = true;
  182. return *this;
  183. }
  184. template <class CTO, class CBO>
  185. std::enable_if_t<conjunction<
  186. negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
  187. std::is_assignable<std::add_lvalue_reference_t<CT>, CTO>,
  188. negation<detail::converts_from_xoptional<CT, CTO, CBO>>,
  189. negation<detail::assigns_from_xoptional<CT, CTO, CBO>>
  190. >::value,
  191. xoptional&>
  192. inline operator=(const xoptional<CTO, CBO>& rhs)
  193. {
  194. m_value = rhs.value();
  195. m_flag = rhs.has_value();
  196. return *this;
  197. }
  198. template <class CTO, class CBO>
  199. std::enable_if_t<conjunction<
  200. negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
  201. std::is_assignable<std::add_lvalue_reference_t<CT>, CTO>,
  202. negation<detail::converts_from_xoptional<CT, CTO, CBO>>,
  203. negation<detail::assigns_from_xoptional<CT, CTO, CBO>>
  204. >::value,
  205. xoptional&>
  206. inline operator=(xoptional<CTO, CBO>&& rhs)
  207. {
  208. m_value = std::move(rhs).value();
  209. m_flag = std::move(rhs).has_value();
  210. return *this;
  211. }
  212. // Operators
  213. template <class CTO, class CBO>
  214. xoptional& operator+=(const xoptional<CTO, CBO>&);
  215. template <class CTO, class CBO>
  216. xoptional& operator-=(const xoptional<CTO, CBO>&);
  217. template <class CTO, class CBO>
  218. xoptional& operator*=(const xoptional<CTO, CBO>&);
  219. template <class CTO, class CBO>
  220. xoptional& operator/=(const xoptional<CTO, CBO>&);
  221. template <class CTO, class CBO>
  222. xoptional& operator%=(const xoptional<CTO, CBO>&);
  223. template <class CTO, class CBO>
  224. xoptional& operator&=(const xoptional<CTO, CBO>&);
  225. template <class CTO, class CBO>
  226. xoptional& operator|=(const xoptional<CTO, CBO>&);
  227. template <class CTO, class CBO>
  228. xoptional& operator^=(const xoptional<CTO, CBO>&);
  229. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  230. xoptional& operator+=(const T&);
  231. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  232. xoptional& operator-=(const T&);
  233. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  234. xoptional& operator*=(const T&);
  235. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  236. xoptional& operator/=(const T&);
  237. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  238. xoptional& operator%=(const T&);
  239. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  240. xoptional& operator&=(const T&);
  241. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  242. xoptional& operator|=(const T&);
  243. template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
  244. xoptional& operator^=(const T&);
  245. // Access
  246. std::add_lvalue_reference_t<CT> value() & noexcept;
  247. std::add_lvalue_reference_t<std::add_const_t<CT>> value() const & noexcept;
  248. std::conditional_t<std::is_reference<CT>::value, apply_cv_t<CT, value_type>&, value_type> value() && noexcept;
  249. std::conditional_t<std::is_reference<CT>::value, const value_type&, value_type> value() const && noexcept;
  250. template <class U>
  251. value_type value_or(U&&) const & noexcept;
  252. template <class U>
  253. value_type value_or(U&&) const && noexcept;
  254. // Access
  255. std::add_lvalue_reference_t<CB> has_value() & noexcept;
  256. std::add_lvalue_reference_t<std::add_const_t<CB>> has_value() const & noexcept;
  257. std::conditional_t<std::is_reference<CB>::value, apply_cv_t<CB, flag_type>&, flag_type> has_value() && noexcept;
  258. std::conditional_t<std::is_reference<CB>::value, const flag_type&, flag_type> has_value() const && noexcept;
  259. // Swap
  260. void swap(xoptional& other);
  261. // Comparison
  262. template <class CTO, class CBO>
  263. bool equal(const xoptional<CTO, CBO>& rhs) const noexcept;
  264. template <class CTO, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<CTO>)>
  265. bool equal(const CTO& rhs) const noexcept;
  266. xclosure_pointer<self_type&> operator&() &;
  267. xclosure_pointer<const self_type&> operator&() const &;
  268. xclosure_pointer<self_type> operator&() &&;
  269. private:
  270. template <class CTO, class CBO>
  271. friend class xoptional;
  272. CT m_value;
  273. CB m_flag;
  274. };
  275. // value
  276. template <class T, class U = disable_xoptional<std::decay_t<T>>>
  277. T&& value(T&& v)
  278. {
  279. return std::forward<T>(v);
  280. }
  281. template <class CT, class CB>
  282. decltype(auto) value(xtl::xoptional<CT, CB>&& v)
  283. {
  284. return std::move(v).value();
  285. }
  286. template <class CT, class CB>
  287. decltype(auto) value(xtl::xoptional<CT, CB>& v)
  288. {
  289. return v.value();
  290. }
  291. template <class CT, class CB>
  292. decltype(auto) value(const xtl::xoptional<CT, CB>& v)
  293. {
  294. return v.value();
  295. }
  296. // has_value
  297. template <class T, class U = disable_xoptional<std::decay_t<T>>>
  298. bool has_value(T&&)
  299. {
  300. return true;
  301. }
  302. template <class CT, class CB>
  303. decltype(auto) has_value(xtl::xoptional<CT, CB>&& v)
  304. {
  305. return std::move(v).has_value();
  306. }
  307. template <class CT, class CB>
  308. decltype(auto) has_value(xtl::xoptional<CT, CB>& v)
  309. {
  310. return v.has_value();
  311. }
  312. template <class CT, class CB>
  313. decltype(auto) has_value(const xtl::xoptional<CT, CB>& v)
  314. {
  315. return v.has_value();
  316. }
  317. /***************************************
  318. * optional and missing implementation *
  319. ***************************************/
  320. /**
  321. * @brief Returns an \ref xoptional holding closure types on the specified parameters
  322. *
  323. * @tparam t the optional value
  324. * @tparam b the boolean flag
  325. */
  326. template <class T, class B>
  327. inline auto optional(T&& t, B&& b) noexcept
  328. {
  329. using optional_type = xoptional<closure_type_t<T>, closure_type_t<B>>;
  330. return optional_type(std::forward<T>(t), std::forward<B>(b));
  331. }
  332. /**
  333. * @brief Returns an \ref xoptional for a missig value
  334. */
  335. template <class T>
  336. xoptional<T, bool> missing() noexcept
  337. {
  338. return xoptional<T, bool>(T(), false);
  339. }
  340. /****************************
  341. * xoptional implementation *
  342. ****************************/
  343. // Constructors
  344. template <class CT, class CB>
  345. xoptional<CT, CB>::xoptional(value_type&& value, flag_type&& flag)
  346. : m_value(std::move(value)), m_flag(std::move(flag))
  347. {
  348. }
  349. template <class CT, class CB>
  350. xoptional<CT, CB>::xoptional(std::add_lvalue_reference_t<CT> value, std::add_lvalue_reference_t<CB> flag)
  351. : m_value(value), m_flag(flag)
  352. {
  353. }
  354. template <class CT, class CB>
  355. xoptional<CT, CB>::xoptional(value_type&& value, std::add_lvalue_reference_t<CB> flag)
  356. : m_value(std::move(value)), m_flag(flag)
  357. {
  358. }
  359. template <class CT, class CB>
  360. xoptional<CT, CB>::xoptional(std::add_lvalue_reference_t<CT> value, flag_type&& flag)
  361. : m_value(value), m_flag(std::move(flag))
  362. {
  363. }
  364. // Operators
  365. template <class CT, class CB>
  366. template <class CTO, class CBO>
  367. auto xoptional<CT, CB>::operator+=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  368. {
  369. m_flag = m_flag && rhs.m_flag;
  370. if (m_flag)
  371. {
  372. m_value += rhs.m_value;
  373. }
  374. return *this;
  375. }
  376. template <class CT, class CB>
  377. template <class CTO, class CBO>
  378. auto xoptional<CT, CB>::operator-=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  379. {
  380. m_flag = m_flag && rhs.m_flag;
  381. if (m_flag)
  382. {
  383. m_value -= rhs.m_value;
  384. }
  385. return *this;
  386. }
  387. template <class CT, class CB>
  388. template <class CTO, class CBO>
  389. auto xoptional<CT, CB>::operator*=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  390. {
  391. m_flag = m_flag && rhs.m_flag;
  392. if (m_flag)
  393. {
  394. m_value *= rhs.m_value;
  395. }
  396. return *this;
  397. }
  398. template <class CT, class CB>
  399. template <class CTO, class CBO>
  400. auto xoptional<CT, CB>::operator/=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  401. {
  402. m_flag = m_flag && rhs.m_flag;
  403. if (m_flag)
  404. {
  405. m_value /= rhs.m_value;
  406. }
  407. return *this;
  408. }
  409. template <class CT, class CB>
  410. template <class CTO, class CBO>
  411. auto xoptional<CT, CB>::operator%=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  412. {
  413. m_flag = m_flag && rhs.m_flag;
  414. if (m_flag)
  415. {
  416. m_value %= rhs.m_value;
  417. }
  418. return *this;
  419. }
  420. template <class CT, class CB>
  421. template <class CTO, class CBO>
  422. auto xoptional<CT, CB>::operator&=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  423. {
  424. m_flag = m_flag && rhs.m_flag;
  425. if (m_flag)
  426. {
  427. m_value &= rhs.m_value;
  428. }
  429. return *this;
  430. }
  431. template <class CT, class CB>
  432. template <class CTO, class CBO>
  433. auto xoptional<CT, CB>::operator|=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  434. {
  435. m_flag = m_flag && rhs.m_flag;
  436. if (m_flag)
  437. {
  438. m_value |= rhs.m_value;
  439. }
  440. return *this;
  441. }
  442. template <class CT, class CB>
  443. template <class CTO, class CBO>
  444. auto xoptional<CT, CB>::operator^=(const xoptional<CTO, CBO>& rhs) -> xoptional&
  445. {
  446. m_flag = m_flag && rhs.m_flag;
  447. if (m_flag)
  448. {
  449. m_value ^= rhs.m_value;
  450. }
  451. return *this;
  452. }
  453. template <class CT, class CB>
  454. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  455. auto xoptional<CT, CB>::operator+=(const T& rhs) -> xoptional&
  456. {
  457. if (m_flag)
  458. {
  459. m_value += rhs;
  460. }
  461. return *this;
  462. }
  463. template <class CT, class CB>
  464. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  465. auto xoptional<CT, CB>::operator-=(const T& rhs) -> xoptional&
  466. {
  467. if (m_flag)
  468. {
  469. m_value -= rhs;
  470. }
  471. return *this;
  472. }
  473. template <class CT, class CB>
  474. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  475. auto xoptional<CT, CB>::operator*=(const T& rhs) -> xoptional&
  476. {
  477. if (m_flag)
  478. {
  479. m_value *= rhs;
  480. }
  481. return *this;
  482. }
  483. template <class CT, class CB>
  484. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  485. auto xoptional<CT, CB>::operator/=(const T& rhs) -> xoptional&
  486. {
  487. if (m_flag)
  488. {
  489. m_value /= rhs;
  490. }
  491. return *this;
  492. }
  493. template <class CT, class CB>
  494. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  495. auto xoptional<CT, CB>::operator%=(const T& rhs) -> xoptional&
  496. {
  497. if (m_flag)
  498. {
  499. m_value %= rhs;
  500. }
  501. return *this;
  502. }
  503. template <class CT, class CB>
  504. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  505. auto xoptional<CT, CB>::operator&=(const T& rhs) -> xoptional&
  506. {
  507. if (m_flag)
  508. {
  509. m_value &= rhs;
  510. }
  511. return *this;
  512. }
  513. template <class CT, class CB>
  514. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  515. auto xoptional<CT, CB>::operator|=(const T& rhs) -> xoptional&
  516. {
  517. if (m_flag)
  518. {
  519. m_value |= rhs;
  520. }
  521. return *this;
  522. }
  523. template <class CT, class CB>
  524. template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
  525. auto xoptional<CT, CB>::operator^=(const T& rhs) -> xoptional&
  526. {
  527. if (m_flag)
  528. {
  529. m_value ^= rhs;
  530. }
  531. return *this;
  532. }
  533. // Access
  534. template <class CT, class CB>
  535. auto xoptional<CT, CB>::value() & noexcept -> std::add_lvalue_reference_t<CT>
  536. {
  537. return m_value;
  538. }
  539. template <class CT, class CB>
  540. auto xoptional<CT, CB>::value() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<CT>>
  541. {
  542. return m_value;
  543. }
  544. template <class CT, class CB>
  545. auto xoptional<CT, CB>::value() && noexcept -> std::conditional_t<std::is_reference<CT>::value, apply_cv_t<CT, value_type>&, value_type>
  546. {
  547. return m_value;
  548. }
  549. template <class CT, class CB>
  550. auto xoptional<CT, CB>::value() const && noexcept -> std::conditional_t<std::is_reference<CT>::value, const value_type&, value_type>
  551. {
  552. return m_value;
  553. }
  554. template <class CT, class CB>
  555. template <class U>
  556. auto xoptional<CT, CB>::value_or(U&& default_value) const & noexcept -> value_type
  557. {
  558. return m_flag ? m_value : std::forward<U>(default_value);
  559. }
  560. template <class CT, class CB>
  561. template <class U>
  562. auto xoptional<CT, CB>::value_or(U&& default_value) const && noexcept -> value_type
  563. {
  564. return m_flag ? m_value : std::forward<U>(default_value);
  565. }
  566. // Access
  567. template <class CT, class CB>
  568. auto xoptional<CT, CB>::has_value() & noexcept -> std::add_lvalue_reference_t<CB>
  569. {
  570. return m_flag;
  571. }
  572. template <class CT, class CB>
  573. auto xoptional<CT, CB>::has_value() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<CB>>
  574. {
  575. return m_flag;
  576. }
  577. template <class CT, class CB>
  578. auto xoptional<CT, CB>::has_value() && noexcept -> std::conditional_t<std::is_reference<CB>::value, apply_cv_t<CB, flag_type>&, flag_type>
  579. {
  580. return m_flag;
  581. }
  582. template <class CT, class CB>
  583. auto xoptional<CT, CB>::has_value() const && noexcept -> std::conditional_t<std::is_reference<CB>::value, const flag_type&, flag_type>
  584. {
  585. return m_flag;
  586. }
  587. // Swap
  588. template <class CT, class CB>
  589. void xoptional<CT, CB>::swap(xoptional& other)
  590. {
  591. std::swap(m_value, other.m_value);
  592. std::swap(m_flag, other.m_flag);
  593. }
  594. // Comparison
  595. template <class CT, class CB>
  596. template <class CTO, class CBO>
  597. auto xoptional<CT, CB>::equal(const xoptional<CTO, CBO>& rhs) const noexcept -> bool
  598. {
  599. return (!m_flag && !rhs.m_flag) || (m_value == rhs.m_value && (m_flag && rhs.m_flag));
  600. }
  601. template <class CT, class CB>
  602. template <class CTO, check_requires<is_not_xoptional_nor_xmasked_value<CTO>>>
  603. bool xoptional<CT, CB>::equal(const CTO& rhs) const noexcept
  604. {
  605. return m_flag ? (m_value == rhs) : false;
  606. }
  607. template <class CT, class CB>
  608. inline auto xoptional<CT, CB>::operator&() & -> xclosure_pointer<self_type&>
  609. {
  610. return xclosure_pointer<self_type&>(*this);
  611. }
  612. template <class CT, class CB>
  613. inline auto xoptional<CT, CB>::operator&() const & -> xclosure_pointer<const self_type&>
  614. {
  615. return xclosure_pointer<const self_type&>(*this);
  616. }
  617. template <class CT, class CB>
  618. inline auto xoptional<CT, CB>::operator&() && -> xclosure_pointer<self_type>
  619. {
  620. return xclosure_pointer<self_type>(std::move(*this));
  621. }
  622. // External operators
  623. template <class T, class B, class OC, class OT>
  624. inline std::basic_ostream<OC, OT>& operator<<(std::basic_ostream<OC, OT>& out, const xoptional<T, B>& v)
  625. {
  626. if (v.has_value())
  627. {
  628. out << v.value();
  629. }
  630. else
  631. {
  632. out << "N/A";
  633. }
  634. return out;
  635. }
  636. #ifdef __CLING__
  637. template <class T, class B>
  638. nlohmann::json mime_bundle_repr(const xoptional<T, B>& v)
  639. {
  640. auto bundle = nlohmann::json::object();
  641. std::stringstream tmp;
  642. tmp << v;
  643. bundle["text/plain"] = tmp.str();
  644. return bundle;
  645. }
  646. #endif
  647. template <class T1, class B1, class T2, class B2>
  648. inline auto operator==(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  649. -> bool
  650. {
  651. return e1.equal(e2);
  652. }
  653. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  654. inline bool operator==(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  655. {
  656. return e1.equal(e2);
  657. }
  658. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  659. inline bool operator==(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  660. {
  661. return e2.equal(e1);
  662. }
  663. template <class T, class B>
  664. inline auto operator+(const xoptional<T, B>& e) noexcept
  665. -> xoptional<std::decay_t<T>>
  666. {
  667. return e;
  668. }
  669. template <class T1, class B1, class T2, class B2>
  670. inline auto operator!=(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  671. -> bool
  672. {
  673. return !e1.equal(e2);
  674. }
  675. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  676. inline bool operator!=(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  677. {
  678. return !e1.equal(e2);
  679. }
  680. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  681. inline bool operator!=(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  682. {
  683. return !e2.equal(e1);
  684. }
  685. // Operations
  686. template <class T, class B>
  687. inline auto operator-(const xoptional<T, B>& e) noexcept
  688. -> xoptional<std::decay_t<T>>
  689. {
  690. using value_type = std::decay_t<T>;
  691. return e.has_value() ? -e.value() : missing<value_type>();
  692. }
  693. template <class T1, class B1, class T2, class B2>
  694. inline auto operator+(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  695. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  696. {
  697. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  698. return e1.has_value() && e2.has_value() ? e1.value() + e2.value() : missing<value_type>();
  699. }
  700. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  701. inline auto operator+(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  702. -> common_optional_t<T1, T2>
  703. {
  704. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  705. return e2.has_value() ? e1 + e2.value() : missing<value_type>();
  706. }
  707. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  708. inline auto operator+(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  709. -> common_optional_t<T1, T2>
  710. {
  711. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  712. return e1.has_value() ? e1.value() + e2 : missing<value_type>();
  713. }
  714. template <class T1, class B1, class T2, class B2>
  715. inline auto operator-(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  716. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  717. {
  718. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  719. return e1.has_value() && e2.has_value() ? e1.value() - e2.value() : missing<value_type>();
  720. }
  721. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  722. inline auto operator-(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  723. -> common_optional_t<T1, T2>
  724. {
  725. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  726. return e2.has_value() ? e1 - e2.value() : missing<value_type>();
  727. }
  728. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  729. inline auto operator-(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  730. -> common_optional_t<T1, T2>
  731. {
  732. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  733. return e1.has_value() ? e1.value() - e2 : missing<value_type>();
  734. }
  735. template <class T1, class B1, class T2, class B2>
  736. inline auto operator*(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  737. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  738. {
  739. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  740. return e1.has_value() && e2.has_value() ? e1.value() * e2.value() : missing<value_type>();
  741. }
  742. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  743. inline auto operator*(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  744. -> common_optional_t<T1, T2>
  745. {
  746. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  747. return e2.has_value() ? e1 * e2.value() : missing<value_type>();
  748. }
  749. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  750. inline auto operator*(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  751. -> common_optional_t<T1, T2>
  752. {
  753. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  754. return e1.has_value() ? e1.value() * e2 : missing<value_type>();
  755. }
  756. template <class T1, class B1, class T2, class B2>
  757. inline auto operator/(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  758. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  759. {
  760. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  761. return e1.has_value() && e2.has_value() ? e1.value() / e2.value() : missing<value_type>();
  762. }
  763. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  764. inline auto operator/(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  765. -> common_optional_t<T1, T2>
  766. {
  767. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  768. return e2.has_value() ? e1 / e2.value() : missing<value_type>();
  769. }
  770. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  771. inline auto operator/(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  772. -> common_optional_t<T1, T2>
  773. {
  774. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  775. return e1.has_value() ? e1.value() / e2 : missing<value_type>();
  776. }
  777. template <class T1, class B1, class T2, class B2>
  778. inline auto operator%(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  779. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  780. {
  781. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  782. return e1.has_value() && e2.has_value() ? e1.value() % e2.value() : missing<value_type>();
  783. }
  784. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  785. inline auto operator%(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  786. -> common_optional_t<T1, T2>
  787. {
  788. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  789. return e2.has_value() ? e1 % e2.value() : missing<value_type>();
  790. }
  791. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  792. inline auto operator%(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  793. -> common_optional_t<T1, T2>
  794. {
  795. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  796. return e1.has_value() ? e1.value() % e2 : missing<value_type>();
  797. }
  798. template <class T, class B>
  799. inline auto operator~(const xoptional<T, B>& e) noexcept
  800. -> xoptional<std::decay_t<T>>
  801. {
  802. using value_type = std::decay_t<T>;
  803. return e.has_value() ? ~e.value() : missing<value_type>();
  804. }
  805. template <class T1, class B1, class T2, class B2>
  806. inline auto operator&(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  807. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  808. {
  809. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  810. return e1.has_value() && e2.has_value() ? e1.value() & e2.value() : missing<value_type>();
  811. }
  812. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  813. inline auto operator&(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  814. -> common_optional_t<T1, T2>
  815. {
  816. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  817. return e2.has_value() ? e1 & e2.value() : missing<value_type>();
  818. }
  819. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  820. inline auto operator&(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  821. -> common_optional_t<T1, T2>
  822. {
  823. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  824. return e1.has_value() ? e1.value() & e2 : missing<value_type>();
  825. }
  826. template <class T1, class B1, class T2, class B2>
  827. inline auto operator|(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  828. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  829. {
  830. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  831. return e1.has_value() && e2.has_value() ? e1.value() | e2.value() : missing<value_type>();
  832. }
  833. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  834. inline auto operator|(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  835. -> common_optional_t<T1, T2>
  836. {
  837. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  838. return e2.has_value() ? e1 | e2.value() : missing<value_type>();
  839. }
  840. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  841. inline auto operator|(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  842. -> common_optional_t<T1, T2>
  843. {
  844. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  845. return e1.has_value() ? e1.value() | e2 : missing<value_type>();
  846. }
  847. template <class T1, class B1, class T2, class B2>
  848. inline auto operator^(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  849. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  850. {
  851. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  852. return e1.has_value() && e2.has_value() ? e1.value() ^ e2.value() : missing<value_type>();
  853. }
  854. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  855. inline auto operator^(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  856. -> common_optional_t<T1, T2>
  857. {
  858. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  859. return e2.has_value() ? e1 ^ e2.value() : missing<value_type>();
  860. }
  861. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  862. inline auto operator^(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  863. -> common_optional_t<T1, T2>
  864. {
  865. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  866. return e1.has_value() ? e1.value() ^ e2 : missing<value_type>();
  867. }
  868. template <class T1, class B1, class T2, class B2>
  869. inline auto operator||(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  870. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  871. {
  872. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  873. return e1.has_value() && e2.has_value() ? e1.value() || e2.value() : missing<value_type>();
  874. }
  875. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  876. inline auto operator||(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  877. -> common_optional_t<T1, T2>
  878. {
  879. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  880. return e2.has_value() ? e1 || e2.value() : missing<value_type>();
  881. }
  882. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  883. inline auto operator||(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  884. -> common_optional_t<T1, T2>
  885. {
  886. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  887. return e1.has_value() ? e1.value() || e2 : missing<value_type>();
  888. }
  889. template <class T1, class B1, class T2, class B2>
  890. inline auto operator&&(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  891. -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
  892. {
  893. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  894. return e1.has_value() && e2.has_value() ? e1.value() && e2.value() : missing<value_type>();
  895. }
  896. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  897. inline auto operator&&(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  898. -> common_optional_t<T1, T2>
  899. {
  900. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  901. return e2.has_value() ? e1 && e2.value() : missing<value_type>();
  902. }
  903. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  904. inline auto operator&&(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  905. -> common_optional_t<T1, T2>
  906. {
  907. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
  908. return e1.has_value() ? e1.value() && e2 : missing<value_type>();
  909. }
  910. template <class T, class B>
  911. inline auto operator!(const xoptional<T, B>& e) noexcept
  912. -> xoptional<bool>
  913. {
  914. return e.has_value() ? !e.value() : missing<bool>();
  915. }
  916. template <class T1, class B1, class T2, class B2>
  917. inline auto operator<(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  918. -> xoptional<bool>
  919. {
  920. return e1.has_value() && e2.has_value() ? e1.value() < e2.value() : missing<bool>();
  921. }
  922. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  923. inline auto operator<(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  924. -> xoptional<bool>
  925. {
  926. return e2.has_value() ? e1 < e2.value() : missing<bool>();
  927. }
  928. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  929. inline auto operator<(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  930. -> xoptional<bool>
  931. {
  932. return e1.has_value() ? e1.value() < e2 : missing<bool>();
  933. }
  934. template <class T1, class B1, class T2, class B2>
  935. inline auto operator<=(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  936. -> xoptional<bool>
  937. {
  938. return e1.has_value() && e2.has_value() ? e1.value() <= e2.value() : missing<bool>();
  939. }
  940. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  941. inline auto operator<=(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  942. -> xoptional<bool>
  943. {
  944. return e2.has_value() ? e1 <= e2.value() : missing<bool>();
  945. }
  946. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  947. inline auto operator<=(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  948. -> xoptional<bool>
  949. {
  950. return e1.has_value() ? e1.value() <= e2 : missing<bool>();
  951. }
  952. template <class T1, class B1, class T2, class B2>
  953. inline auto operator>(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  954. -> xoptional<bool>
  955. {
  956. return e1.has_value() && e2.has_value() ? e1.value() > e2.value() : missing<bool>();
  957. }
  958. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  959. inline auto operator>(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  960. -> xoptional<bool>
  961. {
  962. return e2.has_value() ? e1 > e2.value() : missing<bool>();
  963. }
  964. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  965. inline auto operator>(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  966. -> xoptional<bool>
  967. {
  968. return e1.has_value() ? e1.value() > e2 : missing<bool>();
  969. }
  970. template <class T1, class B1, class T2, class B2>
  971. inline auto operator>=(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
  972. -> xoptional<bool>
  973. {
  974. return e1.has_value() && e2.has_value() ? e1.value() >= e2.value() : missing<bool>();
  975. }
  976. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
  977. inline auto operator>=(const T1& e1, const xoptional<T2, B2>& e2) noexcept
  978. -> xoptional<bool>
  979. {
  980. return e2.has_value() ? e1 >= e2.value() : missing<bool>();
  981. }
  982. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
  983. inline auto operator>=(const xoptional<T1, B1>& e1, const T2& e2) noexcept
  984. -> xoptional<bool>
  985. {
  986. return e1.has_value() ? e1.value() >= e2 : missing<bool>();
  987. }
  988. #define UNARY_OPTIONAL(NAME) \
  989. template <class T, class B> \
  990. inline auto NAME(const xoptional<T, B>& e) \
  991. { \
  992. using std::NAME; \
  993. return e.has_value() ? NAME(e.value()) : missing<std::decay_t<T>>(); \
  994. }
  995. #define UNARY_BOOL_OPTIONAL(NAME) \
  996. template <class T, class B> \
  997. inline xoptional<bool> NAME(const xoptional<T, B>& e) \
  998. { \
  999. using std::NAME; \
  1000. return e.has_value() ? bool(NAME(e.value())) : missing<bool>(); \
  1001. }
  1002. #define BINARY_OPTIONAL_1(NAME) \
  1003. template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)> \
  1004. inline auto NAME(const xoptional<T1, B1>& e1, const T2& e2) \
  1005. -> common_optional_t<T1, T2> \
  1006. { \
  1007. using std::NAME; \
  1008. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
  1009. return e1.has_value() ? NAME(e1.value(), e2) : missing<value_type>(); \
  1010. }
  1011. #define BINARY_OPTIONAL_2(NAME) \
  1012. template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)> \
  1013. inline auto NAME(const T1& e1, const xoptional<T2, B2>& e2) \
  1014. -> common_optional_t<T1, T2> \
  1015. { \
  1016. using std::NAME; \
  1017. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
  1018. return e2.has_value() ? NAME(e1, e2.value()) : missing<value_type>(); \
  1019. }
  1020. #define BINARY_OPTIONAL_12(NAME) \
  1021. template <class T1, class B1, class T2, class B2> \
  1022. inline auto NAME(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) \
  1023. { \
  1024. using std::NAME; \
  1025. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
  1026. return e1.has_value() && e2.has_value() ? NAME(e1.value(), e2.value()) : missing<value_type>(); \
  1027. }
  1028. #define BINARY_OPTIONAL(NAME) \
  1029. BINARY_OPTIONAL_1(NAME) \
  1030. BINARY_OPTIONAL_2(NAME) \
  1031. BINARY_OPTIONAL_12(NAME)
  1032. #define TERNARY_OPTIONAL_1(NAME) \
  1033. template <class T1, class B1, class T2, class T3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>, is_not_xoptional_nor_xmasked_value<T3>)> \
  1034. inline auto NAME(const xoptional<T1, B1>& e1, const T2& e2, const T3& e3) \
  1035. -> common_optional_t<T1, T2, T3> \
  1036. { \
  1037. using std::NAME; \
  1038. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
  1039. return e1.has_value() ? NAME(e1.value(), e2, e3) : missing<value_type>(); \
  1040. }
  1041. #define TERNARY_OPTIONAL_2(NAME) \
  1042. template <class T1, class T2, class B2, class T3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>, is_not_xoptional_nor_xmasked_value<T3>)> \
  1043. inline auto NAME(const T1& e1, const xoptional<T2, B2>& e2, const T3& e3) \
  1044. -> common_optional_t<T1, T2, T3> \
  1045. { \
  1046. using std::NAME; \
  1047. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
  1048. return e2.has_value() ? NAME(e1, e2.value(), e3) : missing<value_type>(); \
  1049. }
  1050. #define TERNARY_OPTIONAL_3(NAME) \
  1051. template <class T1, class T2, class T3, class B3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>, is_not_xoptional_nor_xmasked_value<T2>)> \
  1052. inline auto NAME(const T1& e1, const T2& e2, const xoptional<T3, B3>& e3) \
  1053. -> common_optional_t<T1, T2, T3> \
  1054. { \
  1055. using std::NAME; \
  1056. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
  1057. return e3.has_value() ? NAME(e1, e2, e3.value()) : missing<value_type>(); \
  1058. }
  1059. #define TERNARY_OPTIONAL_12(NAME) \
  1060. template <class T1, class B1, class T2, class B2, class T3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T3>)> \
  1061. inline auto NAME(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2, const T3& e3) \
  1062. -> common_optional_t<T1, T2, T3> \
  1063. { \
  1064. using std::NAME; \
  1065. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
  1066. return (e1.has_value() && e2.has_value()) ? NAME(e1.value(), e2.value(), e3) : missing<value_type>(); \
  1067. }
  1068. #define TERNARY_OPTIONAL_13(NAME) \
  1069. template <class T1, class B1, class T2, class T3, class B3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)> \
  1070. inline auto NAME(const xoptional<T1, B1>& e1, const T2& e2, const xoptional<T3, B3>& e3) \
  1071. -> common_optional_t<T1, T2, T3> \
  1072. { \
  1073. using std::NAME; \
  1074. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
  1075. return (e1.has_value() && e3.has_value()) ? NAME(e1.value(), e2, e3.value()) : missing<value_type>(); \
  1076. }
  1077. #define TERNARY_OPTIONAL_23(NAME) \
  1078. template <class T1, class T2, class B2, class T3, class B3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)> \
  1079. inline auto NAME(const T1& e1, const xoptional<T2, B2>& e2, const xoptional<T3, B3>& e3) \
  1080. -> common_optional_t<T1, T2, T3> \
  1081. { \
  1082. using std::NAME; \
  1083. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
  1084. return (e2.has_value() && e3.has_value()) ? NAME(e1, e2.value(), e3.value()) : missing<value_type>(); \
  1085. }
  1086. #define TERNARY_OPTIONAL_123(NAME) \
  1087. template <class T1, class B1, class T2, class B2, class T3, class B3> \
  1088. inline auto NAME(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2, const xoptional<T3, B3>& e3) \
  1089. { \
  1090. using std::NAME; \
  1091. using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
  1092. return (e1.has_value() && e2.has_value() && e3.has_value()) ? NAME(e1.value(), e2.value(), e3.value()) : missing<value_type>(); \
  1093. }
  1094. #define TERNARY_OPTIONAL(NAME) \
  1095. TERNARY_OPTIONAL_1(NAME) \
  1096. TERNARY_OPTIONAL_2(NAME) \
  1097. TERNARY_OPTIONAL_3(NAME) \
  1098. TERNARY_OPTIONAL_12(NAME) \
  1099. TERNARY_OPTIONAL_13(NAME) \
  1100. TERNARY_OPTIONAL_23(NAME) \
  1101. TERNARY_OPTIONAL_123(NAME)
  1102. UNARY_OPTIONAL(abs)
  1103. UNARY_OPTIONAL(fabs)
  1104. BINARY_OPTIONAL(fmod)
  1105. BINARY_OPTIONAL(remainder)
  1106. TERNARY_OPTIONAL(fma)
  1107. BINARY_OPTIONAL(fmax)
  1108. BINARY_OPTIONAL(fmin)
  1109. BINARY_OPTIONAL(fdim)
  1110. UNARY_OPTIONAL(exp)
  1111. UNARY_OPTIONAL(exp2)
  1112. UNARY_OPTIONAL(expm1)
  1113. UNARY_OPTIONAL(log)
  1114. UNARY_OPTIONAL(log10)
  1115. UNARY_OPTIONAL(log2)
  1116. UNARY_OPTIONAL(log1p)
  1117. BINARY_OPTIONAL(pow)
  1118. UNARY_OPTIONAL(sqrt)
  1119. UNARY_OPTIONAL(cbrt)
  1120. BINARY_OPTIONAL(hypot)
  1121. UNARY_OPTIONAL(sin)
  1122. UNARY_OPTIONAL(cos)
  1123. UNARY_OPTIONAL(tan)
  1124. UNARY_OPTIONAL(acos)
  1125. UNARY_OPTIONAL(asin)
  1126. UNARY_OPTIONAL(atan)
  1127. BINARY_OPTIONAL(atan2)
  1128. UNARY_OPTIONAL(sinh)
  1129. UNARY_OPTIONAL(cosh)
  1130. UNARY_OPTIONAL(tanh)
  1131. UNARY_OPTIONAL(acosh)
  1132. UNARY_OPTIONAL(asinh)
  1133. UNARY_OPTIONAL(atanh)
  1134. UNARY_OPTIONAL(erf)
  1135. UNARY_OPTIONAL(erfc)
  1136. UNARY_OPTIONAL(tgamma)
  1137. UNARY_OPTIONAL(lgamma)
  1138. UNARY_OPTIONAL(ceil)
  1139. UNARY_OPTIONAL(floor)
  1140. UNARY_OPTIONAL(trunc)
  1141. UNARY_OPTIONAL(round)
  1142. UNARY_OPTIONAL(nearbyint)
  1143. UNARY_OPTIONAL(rint)
  1144. UNARY_BOOL_OPTIONAL(isfinite)
  1145. UNARY_BOOL_OPTIONAL(isinf)
  1146. UNARY_BOOL_OPTIONAL(isnan)
  1147. #undef TERNARY_OPTIONAL
  1148. #undef TERNARY_OPTIONAL_123
  1149. #undef TERNARY_OPTIONAL_23
  1150. #undef TERNARY_OPTIONAL_13
  1151. #undef TERNARY_OPTIONAL_12
  1152. #undef TERNARY_OPTIONAL_3
  1153. #undef TERNARY_OPTIONAL_2
  1154. #undef TERNARY_OPTIONAL_1
  1155. #undef BINARY_OPTIONAL
  1156. #undef BINARY_OPTIONAL_12
  1157. #undef BINARY_OPTIONAL_2
  1158. #undef BINARY_OPTIONAL_1
  1159. #undef UNARY_OPTIONAL
  1160. /*************************
  1161. * select implementation *
  1162. *************************/
  1163. template <class B, class T1, class T2, XTL_REQUIRES(at_least_one_xoptional<B, T1, T2>)>
  1164. inline common_optional_t<T1, T2> select(const B& cond, const T1& v1, const T2& v2) noexcept
  1165. {
  1166. using bool_type = common_optional_t<B>;
  1167. using return_type = common_optional_t<T1, T2>;
  1168. bool_type opt_cond(cond);
  1169. return opt_cond.has_value() ?
  1170. opt_cond.value() ? return_type(v1) : return_type(v2) :
  1171. missing<typename return_type::value_type>();
  1172. }
  1173. }
  1174. #endif