| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331 |
- /***************************************************************************
- * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
- * Copyright (c) QuantStack *
- * *
- * Distributed under the terms of the BSD 3-Clause License. *
- * *
- * The full license is in the file LICENSE, distributed with this software. *
- ****************************************************************************/
- #ifndef XTL_OPTIONAL_HPP
- #define XTL_OPTIONAL_HPP
- #include <cmath>
- #include <ostream>
- #include <type_traits>
- #include <utility>
- #ifdef __CLING__
- #include <nlohmann/json.hpp>
- #endif
- #include "xoptional_meta.hpp"
- #include "xclosure.hpp"
- #include "xfunctional.hpp"
- #include "xmeta_utils.hpp"
- #include "xtl_config.hpp"
- #include "xtype_traits.hpp"
- namespace xtl
- {
- template <class T, class B>
- auto optional(T&& t, B&& b) noexcept;
- /************************
- * optional declaration *
- ************************/
- /**
- * @class xoptional
- * @brief Optional value handler.
- *
- * The xoptional is an optional proxy. It holds a value (or a reference on a value) and a flag (or reference on a flag)
- * indicating whether the element should be considered missing.
- *
- * xoptional is different from std::optional
- *
- * - no `operator->()` that returns a pointer.
- * - no `operator*()` that returns a value.
- *
- * The only way to access the underlying value and flag is with the `value` and `value_or` methods.
- *
- * - no explicit convertion to bool. This may lead to confusion when the underlying value type is boolean too.
- *
- * @tparam CT Closure type for the value.
- * @tparam CB Closure type for the missing flag. A falsy flag means that the value is missing.
- *
- * \ref xoptional is used both as a value type (with CT and CB being value types) and reference type for containers
- * with CT and CB being reference types. In other words, it serves as a reference proxy.
- *
- */
- template <class CT, class CB>
- class xoptional
- {
- public:
- using self_type = xoptional<CT, CB>;
- using value_closure = CT;
- using flag_closure = CB;
- using value_type = std::decay_t<CT>;
- using flag_type = std::decay_t<CB>;
- // Constructors
- inline xoptional()
- : m_value(), m_flag(false)
- {
- }
- template <class T,
- std::enable_if_t<
- conjunction<
- negation<std::is_same<xoptional<CT, CB>, std::decay_t<T>>>,
- std::is_constructible<CT, T&&>,
- std::is_convertible<T&&, CT>
- >::value,
- bool
- > = true>
- inline constexpr xoptional(T&& rhs)
- : m_value(std::forward<T>(rhs)), m_flag(true)
- {
- }
- template <class T,
- std::enable_if_t<
- conjunction<
- negation<std::is_same<xoptional<CT, CB>, std::decay_t<T>>>,
- std::is_constructible<CT, T&&>,
- negation<std::is_convertible<T&&, CT>>
- >::value,
- bool
- > = false>
- inline explicit constexpr xoptional(T&& value)
- : m_value(std::forward<T>(value)), m_flag(true)
- {
- }
- template <class CTO, class CBO,
- std::enable_if_t<
- conjunction<
- negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
- std::is_constructible<CT, std::add_lvalue_reference_t<std::add_const_t<CTO>>>,
- std::is_constructible<CB, std::add_lvalue_reference_t<std::add_const_t<CBO>>>,
- conjunction<
- std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CTO>>, CT>,
- std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CBO>>, CB>
- >,
- negation<detail::converts_from_xoptional<CT, CTO, CBO>>
- >::value,
- bool
- > = true>
- inline constexpr xoptional(const xoptional<CTO, CBO>& rhs)
- : m_value(rhs.value()), m_flag(rhs.has_value())
- {
- }
- template <class CTO, class CBO,
- std::enable_if_t<
- conjunction<
- negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
- std::is_constructible<CT, std::add_lvalue_reference_t<std::add_const_t<CTO>>>,
- std::is_constructible<CB, std::add_lvalue_reference_t<std::add_const_t<CBO>>>,
- disjunction<
- negation<std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CTO>>, CT>>,
- negation<std::is_convertible<std::add_lvalue_reference_t<std::add_const_t<CBO>>, CB>>
- >,
- negation<detail::converts_from_xoptional<CT, CTO, CBO>>
- >::value,
- bool
- > = false>
- inline explicit constexpr xoptional(const xoptional<CTO, CBO>& rhs)
- : m_value(rhs.value()), m_flag(rhs.has_value())
- {
- }
- template <class CTO, class CBO,
- std::enable_if_t<
- conjunction<
- negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
- std::is_constructible<CT, std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>>,
- std::is_constructible<CB, std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>>,
- conjunction<
- std::is_convertible<std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>, CT>,
- std::is_convertible<std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>, CB>
- >,
- negation<detail::converts_from_xoptional<CT, CTO, CBO>>
- >::value,
- bool
- > = true>
- inline constexpr xoptional(xoptional<CTO, CBO>&& rhs)
- : m_value(std::move(rhs).value()), m_flag(std::move(rhs).has_value())
- {
- }
- template <class CTO, class CBO,
- std::enable_if_t<
- conjunction<
- negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
- std::is_constructible<CT, std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>>,
- std::is_constructible<CB, std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>>,
- disjunction<
- negation<std::is_convertible<std::conditional_t<std::is_reference<CT>::value, const std::decay_t<CTO>&, std::decay_t<CTO>&&>, CT>>,
- negation<std::is_convertible<std::conditional_t<std::is_reference<CB>::value, const std::decay_t<CBO>&, std::decay_t<CBO>&&>, CB>>
- >,
- negation<detail::converts_from_xoptional<CT, CTO, CBO>>
- >::value,
- bool
- > = false>
- inline explicit constexpr xoptional(xoptional<CTO, CBO>&& rhs)
- : m_value(std::move(rhs).value()), m_flag(std::move(rhs).has_value())
- {
- }
- xoptional(value_type&&, flag_type&&);
- xoptional(std::add_lvalue_reference_t<CT>, std::add_lvalue_reference_t<CB>);
- xoptional(value_type&&, std::add_lvalue_reference_t<CB>);
- xoptional(std::add_lvalue_reference_t<CT>, flag_type&&);
- // Assignment
- template <class T>
- std::enable_if_t<
- conjunction<
- negation<std::is_same<xoptional<CT, CB>, std::decay_t<T>>>,
- std::is_assignable<std::add_lvalue_reference_t<CT>, T>
- >::value,
- xoptional&>
- inline operator=(T&& rhs)
- {
- m_value = std::forward<T>(rhs);
- m_flag = true;
- return *this;
- }
- template <class CTO, class CBO>
- std::enable_if_t<conjunction<
- negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
- std::is_assignable<std::add_lvalue_reference_t<CT>, CTO>,
- negation<detail::converts_from_xoptional<CT, CTO, CBO>>,
- negation<detail::assigns_from_xoptional<CT, CTO, CBO>>
- >::value,
- xoptional&>
- inline operator=(const xoptional<CTO, CBO>& rhs)
- {
- m_value = rhs.value();
- m_flag = rhs.has_value();
- return *this;
- }
- template <class CTO, class CBO>
- std::enable_if_t<conjunction<
- negation<std::is_same<xoptional<CT, CB>, xoptional<CTO, CBO>>>,
- std::is_assignable<std::add_lvalue_reference_t<CT>, CTO>,
- negation<detail::converts_from_xoptional<CT, CTO, CBO>>,
- negation<detail::assigns_from_xoptional<CT, CTO, CBO>>
- >::value,
- xoptional&>
- inline operator=(xoptional<CTO, CBO>&& rhs)
- {
- m_value = std::move(rhs).value();
- m_flag = std::move(rhs).has_value();
- return *this;
- }
- // Operators
- template <class CTO, class CBO>
- xoptional& operator+=(const xoptional<CTO, CBO>&);
- template <class CTO, class CBO>
- xoptional& operator-=(const xoptional<CTO, CBO>&);
- template <class CTO, class CBO>
- xoptional& operator*=(const xoptional<CTO, CBO>&);
- template <class CTO, class CBO>
- xoptional& operator/=(const xoptional<CTO, CBO>&);
- template <class CTO, class CBO>
- xoptional& operator%=(const xoptional<CTO, CBO>&);
- template <class CTO, class CBO>
- xoptional& operator&=(const xoptional<CTO, CBO>&);
- template <class CTO, class CBO>
- xoptional& operator|=(const xoptional<CTO, CBO>&);
- template <class CTO, class CBO>
- xoptional& operator^=(const xoptional<CTO, CBO>&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator+=(const T&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator-=(const T&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator*=(const T&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator/=(const T&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator%=(const T&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator&=(const T&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator|=(const T&);
- template <class T, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T>)>
- xoptional& operator^=(const T&);
- // Access
- std::add_lvalue_reference_t<CT> value() & noexcept;
- std::add_lvalue_reference_t<std::add_const_t<CT>> value() const & noexcept;
- std::conditional_t<std::is_reference<CT>::value, apply_cv_t<CT, value_type>&, value_type> value() && noexcept;
- std::conditional_t<std::is_reference<CT>::value, const value_type&, value_type> value() const && noexcept;
- template <class U>
- value_type value_or(U&&) const & noexcept;
- template <class U>
- value_type value_or(U&&) const && noexcept;
- // Access
- std::add_lvalue_reference_t<CB> has_value() & noexcept;
- std::add_lvalue_reference_t<std::add_const_t<CB>> has_value() const & noexcept;
- std::conditional_t<std::is_reference<CB>::value, apply_cv_t<CB, flag_type>&, flag_type> has_value() && noexcept;
- std::conditional_t<std::is_reference<CB>::value, const flag_type&, flag_type> has_value() const && noexcept;
- // Swap
- void swap(xoptional& other);
- // Comparison
- template <class CTO, class CBO>
- bool equal(const xoptional<CTO, CBO>& rhs) const noexcept;
- template <class CTO, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<CTO>)>
- bool equal(const CTO& rhs) const noexcept;
- xclosure_pointer<self_type&> operator&() &;
- xclosure_pointer<const self_type&> operator&() const &;
- xclosure_pointer<self_type> operator&() &&;
- private:
- template <class CTO, class CBO>
- friend class xoptional;
- CT m_value;
- CB m_flag;
- };
- // value
- template <class T, class U = disable_xoptional<std::decay_t<T>>>
- T&& value(T&& v)
- {
- return std::forward<T>(v);
- }
- template <class CT, class CB>
- decltype(auto) value(xtl::xoptional<CT, CB>&& v)
- {
- return std::move(v).value();
- }
- template <class CT, class CB>
- decltype(auto) value(xtl::xoptional<CT, CB>& v)
- {
- return v.value();
- }
- template <class CT, class CB>
- decltype(auto) value(const xtl::xoptional<CT, CB>& v)
- {
- return v.value();
- }
- // has_value
- template <class T, class U = disable_xoptional<std::decay_t<T>>>
- bool has_value(T&&)
- {
- return true;
- }
- template <class CT, class CB>
- decltype(auto) has_value(xtl::xoptional<CT, CB>&& v)
- {
- return std::move(v).has_value();
- }
- template <class CT, class CB>
- decltype(auto) has_value(xtl::xoptional<CT, CB>& v)
- {
- return v.has_value();
- }
- template <class CT, class CB>
- decltype(auto) has_value(const xtl::xoptional<CT, CB>& v)
- {
- return v.has_value();
- }
- /***************************************
- * optional and missing implementation *
- ***************************************/
- /**
- * @brief Returns an \ref xoptional holding closure types on the specified parameters
- *
- * @tparam t the optional value
- * @tparam b the boolean flag
- */
- template <class T, class B>
- inline auto optional(T&& t, B&& b) noexcept
- {
- using optional_type = xoptional<closure_type_t<T>, closure_type_t<B>>;
- return optional_type(std::forward<T>(t), std::forward<B>(b));
- }
- /**
- * @brief Returns an \ref xoptional for a missig value
- */
- template <class T>
- xoptional<T, bool> missing() noexcept
- {
- return xoptional<T, bool>(T(), false);
- }
- /****************************
- * xoptional implementation *
- ****************************/
- // Constructors
- template <class CT, class CB>
- xoptional<CT, CB>::xoptional(value_type&& value, flag_type&& flag)
- : m_value(std::move(value)), m_flag(std::move(flag))
- {
- }
- template <class CT, class CB>
- xoptional<CT, CB>::xoptional(std::add_lvalue_reference_t<CT> value, std::add_lvalue_reference_t<CB> flag)
- : m_value(value), m_flag(flag)
- {
- }
- template <class CT, class CB>
- xoptional<CT, CB>::xoptional(value_type&& value, std::add_lvalue_reference_t<CB> flag)
- : m_value(std::move(value)), m_flag(flag)
- {
- }
- template <class CT, class CB>
- xoptional<CT, CB>::xoptional(std::add_lvalue_reference_t<CT> value, flag_type&& flag)
- : m_value(value), m_flag(std::move(flag))
- {
- }
- // Operators
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator+=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value += rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator-=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value -= rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator*=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value *= rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator/=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value /= rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator%=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value %= rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator&=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value &= rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator|=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value |= rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::operator^=(const xoptional<CTO, CBO>& rhs) -> xoptional&
- {
- m_flag = m_flag && rhs.m_flag;
- if (m_flag)
- {
- m_value ^= rhs.m_value;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator+=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value += rhs;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator-=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value -= rhs;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator*=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value *= rhs;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator/=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value /= rhs;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator%=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value %= rhs;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator&=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value &= rhs;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator|=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value |= rhs;
- }
- return *this;
- }
- template <class CT, class CB>
- template <class T, check_requires<is_not_xoptional_nor_xmasked_value<T>>>
- auto xoptional<CT, CB>::operator^=(const T& rhs) -> xoptional&
- {
- if (m_flag)
- {
- m_value ^= rhs;
- }
- return *this;
- }
- // Access
- template <class CT, class CB>
- auto xoptional<CT, CB>::value() & noexcept -> std::add_lvalue_reference_t<CT>
- {
- return m_value;
- }
- template <class CT, class CB>
- auto xoptional<CT, CB>::value() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<CT>>
- {
- return m_value;
- }
- template <class CT, class CB>
- auto xoptional<CT, CB>::value() && noexcept -> std::conditional_t<std::is_reference<CT>::value, apply_cv_t<CT, value_type>&, value_type>
- {
- return m_value;
- }
- template <class CT, class CB>
- auto xoptional<CT, CB>::value() const && noexcept -> std::conditional_t<std::is_reference<CT>::value, const value_type&, value_type>
- {
- return m_value;
- }
- template <class CT, class CB>
- template <class U>
- auto xoptional<CT, CB>::value_or(U&& default_value) const & noexcept -> value_type
- {
- return m_flag ? m_value : std::forward<U>(default_value);
- }
- template <class CT, class CB>
- template <class U>
- auto xoptional<CT, CB>::value_or(U&& default_value) const && noexcept -> value_type
- {
- return m_flag ? m_value : std::forward<U>(default_value);
- }
- // Access
- template <class CT, class CB>
- auto xoptional<CT, CB>::has_value() & noexcept -> std::add_lvalue_reference_t<CB>
- {
- return m_flag;
- }
- template <class CT, class CB>
- auto xoptional<CT, CB>::has_value() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<CB>>
- {
- return m_flag;
- }
- template <class CT, class CB>
- auto xoptional<CT, CB>::has_value() && noexcept -> std::conditional_t<std::is_reference<CB>::value, apply_cv_t<CB, flag_type>&, flag_type>
- {
- return m_flag;
- }
- template <class CT, class CB>
- auto xoptional<CT, CB>::has_value() const && noexcept -> std::conditional_t<std::is_reference<CB>::value, const flag_type&, flag_type>
- {
- return m_flag;
- }
- // Swap
- template <class CT, class CB>
- void xoptional<CT, CB>::swap(xoptional& other)
- {
- std::swap(m_value, other.m_value);
- std::swap(m_flag, other.m_flag);
- }
- // Comparison
- template <class CT, class CB>
- template <class CTO, class CBO>
- auto xoptional<CT, CB>::equal(const xoptional<CTO, CBO>& rhs) const noexcept -> bool
- {
- return (!m_flag && !rhs.m_flag) || (m_value == rhs.m_value && (m_flag && rhs.m_flag));
- }
- template <class CT, class CB>
- template <class CTO, check_requires<is_not_xoptional_nor_xmasked_value<CTO>>>
- bool xoptional<CT, CB>::equal(const CTO& rhs) const noexcept
- {
- return m_flag ? (m_value == rhs) : false;
- }
- template <class CT, class CB>
- inline auto xoptional<CT, CB>::operator&() & -> xclosure_pointer<self_type&>
- {
- return xclosure_pointer<self_type&>(*this);
- }
- template <class CT, class CB>
- inline auto xoptional<CT, CB>::operator&() const & -> xclosure_pointer<const self_type&>
- {
- return xclosure_pointer<const self_type&>(*this);
- }
- template <class CT, class CB>
- inline auto xoptional<CT, CB>::operator&() && -> xclosure_pointer<self_type>
- {
- return xclosure_pointer<self_type>(std::move(*this));
- }
- // External operators
- template <class T, class B, class OC, class OT>
- inline std::basic_ostream<OC, OT>& operator<<(std::basic_ostream<OC, OT>& out, const xoptional<T, B>& v)
- {
- if (v.has_value())
- {
- out << v.value();
- }
- else
- {
- out << "N/A";
- }
- return out;
- }
- #ifdef __CLING__
- template <class T, class B>
- nlohmann::json mime_bundle_repr(const xoptional<T, B>& v)
- {
- auto bundle = nlohmann::json::object();
- std::stringstream tmp;
- tmp << v;
- bundle["text/plain"] = tmp.str();
- return bundle;
- }
- #endif
- template <class T1, class B1, class T2, class B2>
- inline auto operator==(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> bool
- {
- return e1.equal(e2);
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline bool operator==(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- {
- return e1.equal(e2);
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline bool operator==(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- {
- return e2.equal(e1);
- }
- template <class T, class B>
- inline auto operator+(const xoptional<T, B>& e) noexcept
- -> xoptional<std::decay_t<T>>
- {
- return e;
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator!=(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> bool
- {
- return !e1.equal(e2);
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline bool operator!=(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- {
- return !e1.equal(e2);
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline bool operator!=(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- {
- return !e2.equal(e1);
- }
- // Operations
- template <class T, class B>
- inline auto operator-(const xoptional<T, B>& e) noexcept
- -> xoptional<std::decay_t<T>>
- {
- using value_type = std::decay_t<T>;
- return e.has_value() ? -e.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator+(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() + e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator+(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 + e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator+(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() + e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator-(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() - e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator-(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 - e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator-(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() - e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator*(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() * e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator*(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 * e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator*(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() * e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator/(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() / e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator/(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 / e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator/(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() / e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator%(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() % e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator%(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 % e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator%(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() % e2 : missing<value_type>();
- }
- template <class T, class B>
- inline auto operator~(const xoptional<T, B>& e) noexcept
- -> xoptional<std::decay_t<T>>
- {
- using value_type = std::decay_t<T>;
- return e.has_value() ? ~e.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator&(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() & e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator&(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 & e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator&(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() & e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator|(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() | e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator|(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 | e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator|(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() | e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator^(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() ^ e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator^(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 ^ e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator^(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() ^ e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator||(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() || e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator||(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 || e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator||(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() || e2 : missing<value_type>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator&&(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() && e2.has_value() ? e1.value() && e2.value() : missing<value_type>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator&&(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e2.has_value() ? e1 && e2.value() : missing<value_type>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator&&(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> common_optional_t<T1, T2>
- {
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>;
- return e1.has_value() ? e1.value() && e2 : missing<value_type>();
- }
- template <class T, class B>
- inline auto operator!(const xoptional<T, B>& e) noexcept
- -> xoptional<bool>
- {
- return e.has_value() ? !e.value() : missing<bool>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator<(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() && e2.has_value() ? e1.value() < e2.value() : missing<bool>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator<(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e2.has_value() ? e1 < e2.value() : missing<bool>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator<(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() ? e1.value() < e2 : missing<bool>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator<=(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() && e2.has_value() ? e1.value() <= e2.value() : missing<bool>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator<=(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e2.has_value() ? e1 <= e2.value() : missing<bool>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator<=(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() ? e1.value() <= e2 : missing<bool>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator>(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() && e2.has_value() ? e1.value() > e2.value() : missing<bool>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator>(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e2.has_value() ? e1 > e2.value() : missing<bool>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator>(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() ? e1.value() > e2 : missing<bool>();
- }
- template <class T1, class B1, class T2, class B2>
- inline auto operator>=(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() && e2.has_value() ? e1.value() >= e2.value() : missing<bool>();
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)>
- inline auto operator>=(const T1& e1, const xoptional<T2, B2>& e2) noexcept
- -> xoptional<bool>
- {
- return e2.has_value() ? e1 >= e2.value() : missing<bool>();
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)>
- inline auto operator>=(const xoptional<T1, B1>& e1, const T2& e2) noexcept
- -> xoptional<bool>
- {
- return e1.has_value() ? e1.value() >= e2 : missing<bool>();
- }
- #define UNARY_OPTIONAL(NAME) \
- template <class T, class B> \
- inline auto NAME(const xoptional<T, B>& e) \
- { \
- using std::NAME; \
- return e.has_value() ? NAME(e.value()) : missing<std::decay_t<T>>(); \
- }
- #define UNARY_BOOL_OPTIONAL(NAME) \
- template <class T, class B> \
- inline xoptional<bool> NAME(const xoptional<T, B>& e) \
- { \
- using std::NAME; \
- return e.has_value() ? bool(NAME(e.value())) : missing<bool>(); \
- }
- #define BINARY_OPTIONAL_1(NAME) \
- template <class T1, class B1, class T2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)> \
- inline auto NAME(const xoptional<T1, B1>& e1, const T2& e2) \
- -> common_optional_t<T1, T2> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
- return e1.has_value() ? NAME(e1.value(), e2) : missing<value_type>(); \
- }
- #define BINARY_OPTIONAL_2(NAME) \
- template <class T1, class T2, class B2, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)> \
- inline auto NAME(const T1& e1, const xoptional<T2, B2>& e2) \
- -> common_optional_t<T1, T2> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
- return e2.has_value() ? NAME(e1, e2.value()) : missing<value_type>(); \
- }
- #define BINARY_OPTIONAL_12(NAME) \
- template <class T1, class B1, class T2, class B2> \
- inline auto NAME(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2) \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
- return e1.has_value() && e2.has_value() ? NAME(e1.value(), e2.value()) : missing<value_type>(); \
- }
- #define BINARY_OPTIONAL(NAME) \
- BINARY_OPTIONAL_1(NAME) \
- BINARY_OPTIONAL_2(NAME) \
- BINARY_OPTIONAL_12(NAME)
- #define TERNARY_OPTIONAL_1(NAME) \
- 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>)> \
- inline auto NAME(const xoptional<T1, B1>& e1, const T2& e2, const T3& e3) \
- -> common_optional_t<T1, T2, T3> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
- return e1.has_value() ? NAME(e1.value(), e2, e3) : missing<value_type>(); \
- }
- #define TERNARY_OPTIONAL_2(NAME) \
- 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>)> \
- inline auto NAME(const T1& e1, const xoptional<T2, B2>& e2, const T3& e3) \
- -> common_optional_t<T1, T2, T3> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
- return e2.has_value() ? NAME(e1, e2.value(), e3) : missing<value_type>(); \
- }
- #define TERNARY_OPTIONAL_3(NAME) \
- 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>)> \
- inline auto NAME(const T1& e1, const T2& e2, const xoptional<T3, B3>& e3) \
- -> common_optional_t<T1, T2, T3> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
- return e3.has_value() ? NAME(e1, e2, e3.value()) : missing<value_type>(); \
- }
- #define TERNARY_OPTIONAL_12(NAME) \
- template <class T1, class B1, class T2, class B2, class T3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T3>)> \
- inline auto NAME(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2, const T3& e3) \
- -> common_optional_t<T1, T2, T3> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
- return (e1.has_value() && e2.has_value()) ? NAME(e1.value(), e2.value(), e3) : missing<value_type>(); \
- }
- #define TERNARY_OPTIONAL_13(NAME) \
- template <class T1, class B1, class T2, class T3, class B3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T2>)> \
- inline auto NAME(const xoptional<T1, B1>& e1, const T2& e2, const xoptional<T3, B3>& e3) \
- -> common_optional_t<T1, T2, T3> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
- return (e1.has_value() && e3.has_value()) ? NAME(e1.value(), e2, e3.value()) : missing<value_type>(); \
- }
- #define TERNARY_OPTIONAL_23(NAME) \
- template <class T1, class T2, class B2, class T3, class B3, XTL_REQUIRES(is_not_xoptional_nor_xmasked_value<T1>)> \
- inline auto NAME(const T1& e1, const xoptional<T2, B2>& e2, const xoptional<T3, B3>& e3) \
- -> common_optional_t<T1, T2, T3> \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
- return (e2.has_value() && e3.has_value()) ? NAME(e1, e2.value(), e3.value()) : missing<value_type>(); \
- }
- #define TERNARY_OPTIONAL_123(NAME) \
- template <class T1, class B1, class T2, class B2, class T3, class B3> \
- inline auto NAME(const xoptional<T1, B1>& e1, const xoptional<T2, B2>& e2, const xoptional<T3, B3>& e3) \
- { \
- using std::NAME; \
- using value_type = std::common_type_t<std::decay_t<T1>, std::decay_t<T2>, std::decay_t<T3>>; \
- return (e1.has_value() && e2.has_value() && e3.has_value()) ? NAME(e1.value(), e2.value(), e3.value()) : missing<value_type>(); \
- }
- #define TERNARY_OPTIONAL(NAME) \
- TERNARY_OPTIONAL_1(NAME) \
- TERNARY_OPTIONAL_2(NAME) \
- TERNARY_OPTIONAL_3(NAME) \
- TERNARY_OPTIONAL_12(NAME) \
- TERNARY_OPTIONAL_13(NAME) \
- TERNARY_OPTIONAL_23(NAME) \
- TERNARY_OPTIONAL_123(NAME)
- UNARY_OPTIONAL(abs)
- UNARY_OPTIONAL(fabs)
- BINARY_OPTIONAL(fmod)
- BINARY_OPTIONAL(remainder)
- TERNARY_OPTIONAL(fma)
- BINARY_OPTIONAL(fmax)
- BINARY_OPTIONAL(fmin)
- BINARY_OPTIONAL(fdim)
- UNARY_OPTIONAL(exp)
- UNARY_OPTIONAL(exp2)
- UNARY_OPTIONAL(expm1)
- UNARY_OPTIONAL(log)
- UNARY_OPTIONAL(log10)
- UNARY_OPTIONAL(log2)
- UNARY_OPTIONAL(log1p)
- BINARY_OPTIONAL(pow)
- UNARY_OPTIONAL(sqrt)
- UNARY_OPTIONAL(cbrt)
- BINARY_OPTIONAL(hypot)
- UNARY_OPTIONAL(sin)
- UNARY_OPTIONAL(cos)
- UNARY_OPTIONAL(tan)
- UNARY_OPTIONAL(acos)
- UNARY_OPTIONAL(asin)
- UNARY_OPTIONAL(atan)
- BINARY_OPTIONAL(atan2)
- UNARY_OPTIONAL(sinh)
- UNARY_OPTIONAL(cosh)
- UNARY_OPTIONAL(tanh)
- UNARY_OPTIONAL(acosh)
- UNARY_OPTIONAL(asinh)
- UNARY_OPTIONAL(atanh)
- UNARY_OPTIONAL(erf)
- UNARY_OPTIONAL(erfc)
- UNARY_OPTIONAL(tgamma)
- UNARY_OPTIONAL(lgamma)
- UNARY_OPTIONAL(ceil)
- UNARY_OPTIONAL(floor)
- UNARY_OPTIONAL(trunc)
- UNARY_OPTIONAL(round)
- UNARY_OPTIONAL(nearbyint)
- UNARY_OPTIONAL(rint)
- UNARY_BOOL_OPTIONAL(isfinite)
- UNARY_BOOL_OPTIONAL(isinf)
- UNARY_BOOL_OPTIONAL(isnan)
- #undef TERNARY_OPTIONAL
- #undef TERNARY_OPTIONAL_123
- #undef TERNARY_OPTIONAL_23
- #undef TERNARY_OPTIONAL_13
- #undef TERNARY_OPTIONAL_12
- #undef TERNARY_OPTIONAL_3
- #undef TERNARY_OPTIONAL_2
- #undef TERNARY_OPTIONAL_1
- #undef BINARY_OPTIONAL
- #undef BINARY_OPTIONAL_12
- #undef BINARY_OPTIONAL_2
- #undef BINARY_OPTIONAL_1
- #undef UNARY_OPTIONAL
- /*************************
- * select implementation *
- *************************/
- template <class B, class T1, class T2, XTL_REQUIRES(at_least_one_xoptional<B, T1, T2>)>
- inline common_optional_t<T1, T2> select(const B& cond, const T1& v1, const T2& v2) noexcept
- {
- using bool_type = common_optional_t<B>;
- using return_type = common_optional_t<T1, T2>;
- bool_type opt_cond(cond);
- return opt_cond.has_value() ?
- opt_cond.value() ? return_type(v1) : return_type(v2) :
- missing<typename return_type::value_type>();
- }
- }
- #endif
|