From 1f22aabe21a26768d95fd6eaa3ce5c4da5c36505 Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Sat, 21 Oct 2017 22:31:42 +0100 Subject: [PATCH] Support GCC 4.8 --- README.md | 1 + optional.hpp | 26 +++++++++++++++++++++++++- tests/extensions.cpp | 8 ++++---- tests/observers.cpp | 3 +++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d61ff65..e70bd78 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Tested on: * clang 3.6 * g++ 5.0 * g++ 4.9 + * g++ 4.8 - Appveyor continuous integration * MSVC 2015 * MSVC 2017 diff --git a/optional.hpp b/optional.hpp index fb27242..affebb0 100644 --- a/optional.hpp +++ b/optional.hpp @@ -25,6 +25,10 @@ #define TL_OPTIONAL_GCC49 #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) /// \exclude #define TL_OPTIONAL_11_CONSTEXPR @@ -370,6 +374,7 @@ public: : result(nullopt); } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; template @@ -381,6 +386,7 @@ public: return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); } + #endif /// \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), value())`. Returns a `std::optional`. The return value is empty if `*this` is empty, otherwise an `optional` is constructed from the return value of `std::invoke(std::forward(f), value())` and is returned. @@ -513,6 +519,7 @@ public: return monostate{}; } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \group map /// \synopsis template auto map(F &&f) const &&; template * = nullptr, @@ -554,6 +561,7 @@ public: detail::invoke(*std::forward(f), std::move(**this)); return monostate{}; } + #endif /// \brief Calls `f` if the optional is empty /// \requires `std::invoke_result_t` must be void or convertible to `optional`. @@ -609,6 +617,7 @@ public: return has_value() ? *this : std::forward(f)(); } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \exclude template * = nullptr> optional or_else(F &&f) const && { @@ -624,7 +633,7 @@ public: optional or_else(F &&f) const && { return has_value() ? std::move(*this) : std::forward(f)(); } - + #endif /// \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. @@ -647,11 +656,13 @@ public: : std::forward(u); } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \group map_or template U map_or(F &&f, U &&u) const && { return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u); } + #endif /// \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. @@ -680,6 +691,7 @@ public: : std::forward(u)(); } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \group map_or_else /// \synopsis template \nauto map_or_else(F &&f, U &&u) const &&; template @@ -687,6 +699,7 @@ public: return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u)(); } + #endif /// \returns `u` if `*this` has a value, otherwise an empty optional. template @@ -711,10 +724,12 @@ public: return has_value() ? std::move(*this) : rhs; } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \group disjunction constexpr optional disjunction (const optional &rhs) const && { return has_value() ? std::move(*this) : rhs; } + #endif /// \group disjunction TL_OPTIONAL_11_CONSTEXPR optional disjunction (optional &&rhs) & { @@ -731,10 +746,12 @@ public: return has_value() ? std::move(*this) : std::move(rhs); } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \group disjunction constexpr optional disjunction (optional &&rhs) const && { return has_value() ? std::move(*this) : std::move(rhs); } + #endif /// Takes the value out of the optional, leaving it empty /// \group take @@ -758,12 +775,14 @@ public: return ret; } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \group take optional take() const && { optional ret = std::move(*this); reset(); return ret; } + #endif using value_type = T; @@ -1070,8 +1089,10 @@ public: return std::move(this->m_value); } + #ifndef TL_OPTIONAL_NO_CONSTRR /// \exclude constexpr const T &&operator*() const && { return std::move(this->m_value); } + #endif /// \returns whether or not the optional has a value /// \group has_value @@ -1103,12 +1124,15 @@ public: return std::move(this->m_value); throw bad_optional_access(); } + + #ifndef TL_OPTIONAL_NO_CONSTRR /// \exclude constexpr const T &&value() const && { if (has_value()) return std::move(this->m_value); throw bad_optional_access(); } + #endif /// \returns the stored value if there is one, otherwise returns `u` /// \group value_or diff --git a/tests/extensions.cpp b/tests/extensions.cpp index f4983ab..53172d0 100644 --- a/tests/extensions.cpp +++ b/tests/extensions.cpp @@ -374,18 +374,18 @@ SECTION("conjunction") { SECTION("map_or") { tl::optional 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 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") { tl::optional 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 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") { diff --git a/tests/observers.cpp b/tests/observers.cpp index c5e13d7..642b9f6 100644 --- a/tests/observers.cpp +++ b/tests/observers.cpp @@ -22,8 +22,11 @@ TEST_CASE("Observers", "[observers]") { REQUIRE(success); success = std::is_same::value; REQUIRE(success); + + #ifndef TL_OPTIONAL_NO_CONSTRR success = std::is_same::value; REQUIRE(success); + #endif tl::optional o4{tl::in_place}; move_detector o5 = std::move(o4).value();