mirror of
https://github.com/TartanLlama/optional.git
synced 2025-07-30 18:07:15 +02:00
Support GCC 4.8
This commit is contained in:
@ -77,6 +77,7 @@ Tested on:
|
|||||||
* clang 3.6
|
* clang 3.6
|
||||||
* g++ 5.0
|
* g++ 5.0
|
||||||
* g++ 4.9
|
* g++ 4.9
|
||||||
|
* g++ 4.8
|
||||||
- Appveyor continuous integration
|
- Appveyor continuous integration
|
||||||
* MSVC 2015
|
* MSVC 2015
|
||||||
* MSVC 2017
|
* MSVC 2017
|
||||||
|
26
optional.hpp
26
optional.hpp
@ -25,6 +25,10 @@
|
|||||||
#define TL_OPTIONAL_GCC49
|
#define TL_OPTIONAL_GCC49
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9)
|
||||||
|
#define TL_OPTIONAL_NO_CONSTRR
|
||||||
|
#endif
|
||||||
|
|
||||||
#if __cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || defined(TL_OPTIONAL_GCC49)
|
#if __cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || defined(TL_OPTIONAL_GCC49)
|
||||||
/// \exclude
|
/// \exclude
|
||||||
#define TL_OPTIONAL_11_CONSTEXPR
|
#define TL_OPTIONAL_11_CONSTEXPR
|
||||||
@ -370,6 +374,7 @@ public:
|
|||||||
: result(nullopt);
|
: result(nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \group and_then
|
/// \group and_then
|
||||||
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
/// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&;
|
||||||
template <class F>
|
template <class F>
|
||||||
@ -381,6 +386,7 @@ public:
|
|||||||
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
||||||
: result(nullopt);
|
: result(nullopt);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Carries out some operation on the stored object if there is one.
|
/// \brief Carries out some operation on the stored object if there is one.
|
||||||
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), value())`. Returns a `std::optional<U>`. The return value is empty if `*this` is empty, otherwise an `optional<U>` is constructed from the return value of `std::invoke(std::forward<F>(f), value())` and is returned.
|
/// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), value())`. Returns a `std::optional<U>`. The return value is empty if `*this` is empty, otherwise an `optional<U>` is constructed from the return value of `std::invoke(std::forward<F>(f), value())` and is returned.
|
||||||
@ -513,6 +519,7 @@ public:
|
|||||||
return monostate{};
|
return monostate{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \group map
|
/// \group map
|
||||||
/// \synopsis template <class F> auto map(F &&f) const &&;
|
/// \synopsis template <class F> auto map(F &&f) const &&;
|
||||||
template <class F, detail::disable_if_optional<F> * = nullptr,
|
template <class F, detail::disable_if_optional<F> * = nullptr,
|
||||||
@ -554,6 +561,7 @@ public:
|
|||||||
detail::invoke(*std::forward<F>(f), std::move(**this));
|
detail::invoke(*std::forward<F>(f), std::move(**this));
|
||||||
return monostate{};
|
return monostate{};
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Calls `f` if the optional is empty
|
/// \brief Calls `f` if the optional is empty
|
||||||
/// \requires `std::invoke_result_t<F>` must be void or convertible to `optional<T>`.
|
/// \requires `std::invoke_result_t<F>` must be void or convertible to `optional<T>`.
|
||||||
@ -609,6 +617,7 @@ public:
|
|||||||
return has_value() ? *this : std::forward<F>(f)();
|
return has_value() ? *this : std::forward<F>(f)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \exclude
|
/// \exclude
|
||||||
template <class F, detail::enable_if_ret_void<F> * = nullptr>
|
template <class F, detail::enable_if_ret_void<F> * = nullptr>
|
||||||
optional<T> or_else(F &&f) const && {
|
optional<T> or_else(F &&f) const && {
|
||||||
@ -624,7 +633,7 @@ public:
|
|||||||
optional<T> or_else(F &&f) const && {
|
optional<T> or_else(F &&f) const && {
|
||||||
return has_value() ? std::move(*this) : std::forward<F>(f)();
|
return has_value() ? std::move(*this) : std::forward<F>(f)();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Maps the stored value with `f` if there is one, otherwise returns `u`
|
/// \brief Maps the stored value with `f` if there is one, otherwise returns `u`
|
||||||
/// \details If there is a value stored, then `f` is called with `**this` and the value is returned.
|
/// \details If there is a value stored, then `f` is called with `**this` and the value is returned.
|
||||||
@ -647,11 +656,13 @@ public:
|
|||||||
: std::forward<U>(u);
|
: std::forward<U>(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \group map_or
|
/// \group map_or
|
||||||
template <class F, class U> U map_or(F &&f, U &&u) const && {
|
template <class F, class U> U map_or(F &&f, U &&u) const && {
|
||||||
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
||||||
: std::forward<U>(u);
|
: std::forward<U>(u);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Maps the stored value with `f` if there is one, otherwise calls `u` and returns the result.
|
/// \brief Maps the stored value with `f` if there is one, otherwise calls `u` and returns the result.
|
||||||
/// \details If there is a value stored, then `f` is called with `**this` and the value is returned.
|
/// \details If there is a value stored, then `f` is called with `**this` and the value is returned.
|
||||||
@ -680,6 +691,7 @@ public:
|
|||||||
: std::forward<U>(u)();
|
: std::forward<U>(u)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \group map_or_else
|
/// \group map_or_else
|
||||||
/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) const &&;
|
/// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) const &&;
|
||||||
template <class F, class U>
|
template <class F, class U>
|
||||||
@ -687,6 +699,7 @@ public:
|
|||||||
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this))
|
||||||
: std::forward<U>(u)();
|
: std::forward<U>(u)();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \returns `u` if `*this` has a value, otherwise an empty optional.
|
/// \returns `u` if `*this` has a value, otherwise an empty optional.
|
||||||
template <class U>
|
template <class U>
|
||||||
@ -711,10 +724,12 @@ public:
|
|||||||
return has_value() ? std::move(*this) : rhs;
|
return has_value() ? std::move(*this) : rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \group disjunction
|
/// \group disjunction
|
||||||
constexpr optional disjunction (const optional &rhs) const && {
|
constexpr optional disjunction (const optional &rhs) const && {
|
||||||
return has_value() ? std::move(*this) : rhs;
|
return has_value() ? std::move(*this) : rhs;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \group disjunction
|
/// \group disjunction
|
||||||
TL_OPTIONAL_11_CONSTEXPR optional disjunction (optional &&rhs) & {
|
TL_OPTIONAL_11_CONSTEXPR optional disjunction (optional &&rhs) & {
|
||||||
@ -731,10 +746,12 @@ public:
|
|||||||
return has_value() ? std::move(*this) : std::move(rhs);
|
return has_value() ? std::move(*this) : std::move(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \group disjunction
|
/// \group disjunction
|
||||||
constexpr optional disjunction (optional &&rhs) const && {
|
constexpr optional disjunction (optional &&rhs) const && {
|
||||||
return has_value() ? std::move(*this) : std::move(rhs);
|
return has_value() ? std::move(*this) : std::move(rhs);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Takes the value out of the optional, leaving it empty
|
/// Takes the value out of the optional, leaving it empty
|
||||||
/// \group take
|
/// \group take
|
||||||
@ -758,12 +775,14 @@ public:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \group take
|
/// \group take
|
||||||
optional take() const && {
|
optional take() const && {
|
||||||
optional ret = std::move(*this);
|
optional ret = std::move(*this);
|
||||||
reset();
|
reset();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
@ -1070,8 +1089,10 @@ public:
|
|||||||
return std::move(this->m_value);
|
return std::move(this->m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \exclude
|
/// \exclude
|
||||||
constexpr const T &&operator*() const && { return std::move(this->m_value); }
|
constexpr const T &&operator*() const && { return std::move(this->m_value); }
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \returns whether or not the optional has a value
|
/// \returns whether or not the optional has a value
|
||||||
/// \group has_value
|
/// \group has_value
|
||||||
@ -1103,12 +1124,15 @@ public:
|
|||||||
return std::move(this->m_value);
|
return std::move(this->m_value);
|
||||||
throw bad_optional_access();
|
throw bad_optional_access();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
/// \exclude
|
/// \exclude
|
||||||
constexpr const T &&value() const && {
|
constexpr const T &&value() const && {
|
||||||
if (has_value())
|
if (has_value())
|
||||||
return std::move(this->m_value);
|
return std::move(this->m_value);
|
||||||
throw bad_optional_access();
|
throw bad_optional_access();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \returns the stored value if there is one, otherwise returns `u`
|
/// \returns the stored value if there is one, otherwise returns `u`
|
||||||
/// \group value_or
|
/// \group value_or
|
||||||
|
@ -374,18 +374,18 @@ SECTION("conjunction") {
|
|||||||
|
|
||||||
SECTION("map_or") {
|
SECTION("map_or") {
|
||||||
tl::optional<int> o1 = 21;
|
tl::optional<int> o1 = 21;
|
||||||
REQUIRE((o1.map_or([](auto x) { return x * 2; }, 13)) == 42);
|
REQUIRE((o1.map_or([](int x) { return x * 2; }, 13)) == 42);
|
||||||
|
|
||||||
tl::optional<int> o2;
|
tl::optional<int> o2;
|
||||||
REQUIRE((o2.map_or([](auto x) { return x * 2; }, 13)) == 13);
|
REQUIRE((o2.map_or([](int x) { return x * 2; }, 13)) == 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("map_or_else") {
|
SECTION("map_or_else") {
|
||||||
tl::optional<int> o1 = 21;
|
tl::optional<int> o1 = 21;
|
||||||
REQUIRE((o1.map_or_else([](auto x) { return x * 2; }, []{return 13;})) == 42);
|
REQUIRE((o1.map_or_else([](int x) { return x * 2; }, []{return 13;})) == 42);
|
||||||
|
|
||||||
tl::optional<int> o2;
|
tl::optional<int> o2;
|
||||||
REQUIRE((o2.map_or_else([](auto x) { return x * 2; }, []{return 13;})) == 13);
|
REQUIRE((o2.map_or_else([](int x) { return x * 2; }, []{return 13;})) == 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("take") {
|
SECTION("take") {
|
||||||
|
@ -22,8 +22,11 @@ TEST_CASE("Observers", "[observers]") {
|
|||||||
REQUIRE(success);
|
REQUIRE(success);
|
||||||
success = std::is_same<decltype(std::move(o1).value()), int &&>::value;
|
success = std::is_same<decltype(std::move(o1).value()), int &&>::value;
|
||||||
REQUIRE(success);
|
REQUIRE(success);
|
||||||
|
|
||||||
|
#ifndef TL_OPTIONAL_NO_CONSTRR
|
||||||
success = std::is_same<decltype(std::move(o3).value()), const int &&>::value;
|
success = std::is_same<decltype(std::move(o3).value()), const int &&>::value;
|
||||||
REQUIRE(success);
|
REQUIRE(success);
|
||||||
|
#endif
|
||||||
|
|
||||||
tl::optional<move_detector> o4{tl::in_place};
|
tl::optional<move_detector> o4{tl::in_place};
|
||||||
move_detector o5 = std::move(o4).value();
|
move_detector o5 = std::move(o4).value();
|
||||||
|
Reference in New Issue
Block a user