diff --git a/.travis.yml b/.travis.yml index 66043c7..bad3e69 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: cpp + dist: trusty sudo: false @@ -11,8 +12,24 @@ matrix: sources: - ubuntu-toolchain-r-test packages: - - g++-5 - env: COMPILER=g++-5 CXXSTD=11 + - g++-6 + env: COMPILER=g++-6 CXXSTD=11 + - compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + env: COMPILER=g++-7 CXXSTD=11 + - compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-8 + env: COMPILER=g++-8 CXXSTD=11 - compiler: gcc addons: apt: @@ -80,14 +97,61 @@ matrix: - clang++-3.9 - libc++-dev env: COMPILER=clang++-3.9 CXXSTD=11 + - compiler: clang + addons: + apt: + sources: + - llvm-toolchain-trusty-4.0 + - ubuntu-toolchain-r-test + packages: + - clang++-4.0 + - libc++-dev + env: COMPILER=clang++-4.0 CXXSTD=11 + - compiler: clang + addons: + apt: + sources: + - llvm-toolchain-trusty-5.0 + - ubuntu-toolchain-r-test + packages: + - clang++-5.0 + - libc++-dev + env: COMPILER=clang++-5.0 CXXSTD=11 + - compiler: clang + addons: + apt: + sources: + - llvm-toolchain-trusty-6.0 + - ubuntu-toolchain-r-test + packages: + - clang++-6.0 + - libc++-dev + env: COMPILER=clang++-6.0 CXXSTD=11 + - compiler: gcc addons: apt: sources: - ubuntu-toolchain-r-test packages: - - g++-5 - env: COMPILER=g++-5 CXXSTD=14 + - g++-6 + env: COMPILER=g++-6 CXXSTD=14 + - compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + env: COMPILER=g++-7 CXXSTD=14 + - compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-8 + env: COMPILER=g++-8 CXXSTD=14 - compiler: clang addons: apt: @@ -139,7 +203,36 @@ matrix: - clang++-3.9 - libc++-dev env: COMPILER=clang++-3.9 CXXSTD=14 - + - compiler: clang + addons: + apt: + sources: + - llvm-toolchain-trusty-4.0 + - ubuntu-toolchain-r-test + packages: + - clang++-4.0 + - libc++-dev + env: COMPILER=clang++-4.0 CXXSTD=14 + - compiler: clang + addons: + apt: + sources: + - llvm-toolchain-trusty-5.0 + - ubuntu-toolchain-r-test + packages: + - clang++-5.0 + - libc++-dev + env: COMPILER=clang++-5.0 CXXSTD=14 + - compiler: clang + addons: + apt: + sources: + - llvm-toolchain-trusty-6.0 + - ubuntu-toolchain-r-test + packages: + - clang++-6.0 + - libc++-dev + env: COMPILER=clang++-6.0 CXXSTD=14 install: - if [ "$CXX" = "clang++" ]; then export CXX="$COMPILER -stdlib=libc++"; fi diff --git a/README.md b/README.md index f68fcef..8b7d87d 100644 --- a/README.md +++ b/README.md @@ -90,21 +90,26 @@ o = j; Tested on: -- Linux CI + +- Linux + * clang 6.0.1 + * clang 5.0.2 + * clang 4.0.1 * clang 3.9 * clang 3.8 * clang 3.7 * clang 3.6 * clang 3.5 - * g++ 5.0 + * g++ 8.0.1 + * g++ 7.3 + * g++ 6.4 * g++ 4.9 * g++ 4.8 -- Windows CI +- Windows * MSVC 2015 * MSVC 2017 -- Linux manual - * g++ 7.2 - * g++ 5.4 + +Unfortunately GCC5.5 has a compiler bug which I have not worked around yet. All other GCC5 versions should work. ### Dependencies diff --git a/tests/extensions.cpp b/tests/extensions.cpp index 1524612..9eb024a 100644 --- a/tests/extensions.cpp +++ b/tests/extensions.cpp @@ -237,9 +237,14 @@ TEST_CASE("Monadic operations", "[monadic]") { REQUIRE(!o18r); const tl::optional o19 = tl::nullopt; - auto o19r = - std::move(o19).and_then([](int i) { return tl::make_optional(42); }); + auto o19r = std::move(o19).and_then([](int i) { return tl::make_optional(42); }); REQUIRE(!o19r); + + int i = 3; + tl::optional o20{i}; + std::move(o20).and_then([](int& r){return tl::optional{++r};}); + REQUIRE(o20); + REQUIRE(i == 4); } SECTION("constexpr and_then") { diff --git a/tl/optional.hpp b/tl/optional.hpp index da5bd3f..64e1324 100644 --- a/tl/optional.hpp +++ b/tl/optional.hpp @@ -138,9 +138,9 @@ template struct invoke_result_impl; template struct invoke_result_impl< - F, decltype(invoke(std::declval(), std::declval()...), void()), + F, decltype(detail::invoke(std::declval(), std::declval()...), void()), Us...> { - using type = decltype(invoke(std::declval(), std::declval()...)); + using type = decltype(detail::invoke(std::declval(), std::declval()...)); }; template @@ -1707,11 +1707,11 @@ public: /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) &&; template TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) && { - using result = detail::invoke_result_t; + using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); } @@ -1730,11 +1730,11 @@ public: /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; template constexpr auto and_then(F &&f) const && { - using result = detail::invoke_result_t; + using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); } #endif @@ -1762,12 +1762,12 @@ public: /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) &&; template - TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) && { - using result = detail::invoke_result_t; + TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F &&f) && { + using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); } @@ -1787,12 +1787,12 @@ public: /// \group and_then /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; template - constexpr detail::invoke_result_t and_then(F &&f) const && { - using result = detail::invoke_result_t; + constexpr detail::invoke_result_t and_then(F &&f) const && { + using result = detail::invoke_result_t; static_assert(detail::is_optional::value, "F must return an optional"); - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) + return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); } #endif