From 779cf10329880c229e13e0946d372b3cbd4f1883 Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Mon, 28 May 2018 21:46:58 +0100 Subject: [PATCH 1/5] Qualify call to detail::invoke so that std::invoke isn't picked up due to ADL in C++17 --- tl/optional.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tl/optional.hpp b/tl/optional.hpp index b1d26a6..cdebc24 100644 --- a/tl/optional.hpp +++ b/tl/optional.hpp @@ -133,9 +133,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 From 3a20e3f8cdab944511f7953a59a72145bd350f70 Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Mon, 28 May 2018 22:08:15 +0100 Subject: [PATCH 2/5] Update travis compilers --- .travis.yml | 103 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 5 deletions(-) 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 From f82f78b5b69f3d17309815b1867867a4cfe43c60 Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Mon, 28 May 2018 22:22:28 +0100 Subject: [PATCH 3/5] Update supported compilers --- README.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) 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 From 5143f9577a958d294c3a792c0b368a18704e2cc3 Mon Sep 17 00:00:00 2001 From: Bj?rn Fahller Date: Sun, 3 Jun 2018 12:09:17 +0200 Subject: [PATCH 4/5] 'optional::and_then(F&& f) &&' calls f with lvalue reference This makes sense. The 'optional' is an rvalue, but its contained type remains an lvalue reference. I.e. int i = 3; optional{i}.and_then([](int& r){return optional{++r}); The optional r-value still refers to 'i', which is not an r-value. --- tests/extensions.cpp | 9 +++++++-- tl/optional.hpp | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) 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 cdebc24..35354b3 100644 --- a/tl/optional.hpp +++ b/tl/optional.hpp @@ -1702,11 +1702,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); } @@ -1725,11 +1725,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 From e8b28f2e34e58a3bcb6e68a24c6aa311ec6fe30a Mon Sep 17 00:00:00 2001 From: Bj?rn Fahller Date: Sun, 3 Jun 2018 15:01:57 +0200 Subject: [PATCH 5/5] and the obligatory fixup for C++-11 :-) --- tl/optional.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tl/optional.hpp b/tl/optional.hpp index 35354b3..bc72352 100644 --- a/tl/optional.hpp +++ b/tl/optional.hpp @@ -1757,12 +1757,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); } @@ -1782,12 +1782,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