forked from TartanLlama/optional
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
3452cc1c8c | |||
2ab4f77498 | |||
883df6b427 | |||
f621ca663e | |||
8b408f5fd6 | |||
632bc4e1ad | |||
717027db9b | |||
8c3f042b12 | |||
c4e3b3ee14 | |||
bdaa41ce8c | |||
e589ae4321 | |||
6c73b8113f | |||
32656c4556 | |||
b3dc6d1a52 | |||
247677394f | |||
5a3f094ec7 | |||
26c00afe27 | |||
4308924a38 | |||
6c4178a947 | |||
c67aaff948 | |||
b9486ce776 | |||
a1d27b2aba | |||
d9ce8cf5c5 | |||
e62348c128 | |||
39030e6a00 | |||
4d5f9bd785 | |||
f6802daada | |||
59cf950873 | |||
e4e32ea56d | |||
18a2500d55 | |||
fe07dfaabb | |||
97cdb4e046 | |||
35c7af0b67 | |||
6e9eadc2bd | |||
08550f0959 | |||
0bb694cce8 | |||
adca4b597b | |||
8e7ed1d83c | |||
3720227b2d | |||
45b6e55233 | |||
7cfe5f71e4 | |||
4e00a30e7b | |||
9a6f22d811 | |||
31da15a391 | |||
09249f3be0 | |||
ae88cda44a | |||
1b9d589024 | |||
0df06afe8d | |||
98f34bed66 | |||
9fae73d55b |
77
.travis.yml
77
.travis.yml
@ -12,7 +12,7 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
env: COMPILER=g++-5
|
||||
env: COMPILER=g++-5 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -20,7 +20,7 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.9
|
||||
env: COMPILER=g++-4.9
|
||||
env: COMPILER=g++-4.9 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -28,7 +28,7 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
env: COMPILER=g++-4.8
|
||||
env: COMPILER=g++-4.8 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@ -38,7 +38,7 @@ matrix:
|
||||
packages:
|
||||
- clang++-3.5
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.5
|
||||
env: COMPILER=clang++-3.5 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@ -48,7 +48,7 @@ matrix:
|
||||
packages:
|
||||
- clang++-3.6
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.6
|
||||
env: COMPILER=clang++-3.6 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@ -58,7 +58,7 @@ matrix:
|
||||
packages:
|
||||
- clang++-3.7
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.7
|
||||
env: COMPILER=clang++-3.7 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@ -68,7 +68,7 @@ matrix:
|
||||
packages:
|
||||
- clang++-3.8
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.8
|
||||
env: COMPILER=clang++-3.8 CXXSTD=11
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
@ -79,11 +79,70 @@ matrix:
|
||||
packages:
|
||||
- clang++-3.9
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.9
|
||||
env: COMPILER=clang++-3.9 CXXSTD=11
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-5
|
||||
env: COMPILER=g++-5 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.5
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.5
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.5 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.6
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.6
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.6 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.7
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.7 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.8
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.8
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.8 CXXSTD=14
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-3.9 main"
|
||||
key_url: "http://apt.llvm.org/llvm-snapshot.gpg.key"
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang++-3.9
|
||||
- libc++-dev
|
||||
env: COMPILER=clang++-3.9 CXXSTD=14
|
||||
|
||||
|
||||
install:
|
||||
- if [ "$CXX" = "clang++" ]; then export CXX="$COMPILER -stdlib=libc++"; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="$COMPILER"; fi
|
||||
|
||||
script: mkdir build && cd build && cmake .. && make && ./tests
|
||||
script: mkdir build && cd build && cmake -DCXXSTD=$CXXSTD .. && make && ./tests
|
||||
|
@ -18,24 +18,26 @@ set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/constexpr.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/assignment.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/bases.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tests/nullopt.cpp)
|
||||
|
||||
add_executable(tests ${TEST_SOURCES})
|
||||
|
||||
add_library(optional INTERFACE)
|
||||
target_sources(optional INTERFACE ${CMAKE_SOURCE_DIR}/optional.hpp)
|
||||
target_include_directories(optional INTERFACE ${CMAKE_SOURCE_DIR})
|
||||
target_sources(optional INTERFACE ${CMAKE_SOURCE_DIR}/tl/optional.hpp)
|
||||
target_include_directories(optional INTERFACE ${CMAKE_SOURCE_DIR}/tl)
|
||||
|
||||
target_link_libraries(tests Catch optional)
|
||||
set_property(TARGET tests PROPERTY CXX_STANDARD 14)
|
||||
|
||||
set(CXXSTD 14 CACHE STRING "C++ standard to use, default C++14")
|
||||
set_property(TARGET tests PROPERTY CXX_STANDARD ${CXXSTD})
|
||||
|
||||
find_package(standardese) # find standardese after installation
|
||||
|
||||
# generates a custom target that will run standardese to generate the documentation
|
||||
if (standardese_FOUND)
|
||||
standardese_generate(optional
|
||||
INCLUDE_DIRECTORY .
|
||||
INCLUDE_DIRECTORY tl
|
||||
CONFIG ${CMAKE_SOURCE_DIR}/standardese.config
|
||||
INPUT optional.hpp)
|
||||
INPUT tl/optional.hpp)
|
||||
endif ()
|
||||
|
24
README.md
24
README.md
@ -1,5 +1,5 @@
|
||||
# optional
|
||||
Single header, work-in-progress implementation of `std::optional` with functional-style extensions.
|
||||
Single header implementation of `std::optional` with functional-style extensions and support for references.
|
||||
|
||||
Clang + GCC: [](https://travis-ci.org/TartanLlama/optional)
|
||||
MSVC: [](https://ci.appveyor.com/project/TartanLlama/optional)
|
||||
@ -32,7 +32,7 @@ std::optional<image> get_cute_cat (const image& img) {
|
||||
You can do this:
|
||||
|
||||
```
|
||||
std::optional<image> get_cute_cat (const image& img) {
|
||||
tl::optional<image> get_cute_cat (const image& img) {
|
||||
return crop_to_cat(img)
|
||||
.and_then(add_bow_tie)
|
||||
.and_then(make_eyes_sparkle)
|
||||
@ -66,6 +66,26 @@ The interface is the same as `std::optional`, but the following member functions
|
||||
- `take`: returns the current value, leaving the optional empty.
|
||||
* `opt_string.take().map(&std::string::size); //opt_string now empty;`
|
||||
|
||||
In addition to those member functions, optional references are also supported:
|
||||
|
||||
```
|
||||
int i = 42;
|
||||
tl::optional<int&> o = i;
|
||||
*o == 42; //true
|
||||
i = 12;
|
||||
*o = 12; //true
|
||||
&*o == &i; //true
|
||||
```
|
||||
|
||||
Assignment has rebind semantics rather than assign-through semantics:
|
||||
|
||||
```
|
||||
int j = 8;
|
||||
o = j;
|
||||
|
||||
&*o == &j; //true
|
||||
```
|
||||
|
||||
### Compiler support
|
||||
|
||||
Tested on:
|
||||
|
705
docs/index.md
705
docs/index.md
File diff suppressed because it is too large
Load Diff
1388
optional.hpp
1388
optional.hpp
File diff suppressed because it is too large
Load Diff
3
standardese.config
Normal file
3
standardese.config
Normal file
@ -0,0 +1,3 @@
|
||||
[output]
|
||||
format=commonmark
|
||||
link_extension=html
|
@ -1,7 +1,7 @@
|
||||
#include "catch.hpp"
|
||||
#include "optional.hpp"
|
||||
|
||||
TEST_CASE("Assignment", "[assignment]") {
|
||||
TEST_CASE("Assignment value", "[assignment.value]") {
|
||||
tl::optional<int> o1 = 42;
|
||||
tl::optional<int> o2 = 12;
|
||||
tl::optional<int> o3;
|
||||
@ -32,3 +32,40 @@ TEST_CASE("Assignment", "[assignment]") {
|
||||
o1 = std::move(o4);
|
||||
REQUIRE(*o1 == 42);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Assignment reference", "[assignment.ref]") {
|
||||
auto i = 42;
|
||||
auto j = 12;
|
||||
|
||||
tl::optional<int&> o1 = i;
|
||||
tl::optional<int&> o2 = j;
|
||||
tl::optional<int&> o3;
|
||||
|
||||
o1 = o1;
|
||||
REQUIRE(*o1 == 42);
|
||||
REQUIRE(&*o1 == &i);
|
||||
|
||||
o1 = o2;
|
||||
REQUIRE(*o1 == 12);
|
||||
|
||||
o1 = o3;
|
||||
REQUIRE(!o1);
|
||||
|
||||
auto k = 42;
|
||||
o1 = k;
|
||||
REQUIRE(*o1 == 42);
|
||||
REQUIRE(*o1 == i);
|
||||
REQUIRE(*o1 == k);
|
||||
REQUIRE(&*o1 != &i);
|
||||
REQUIRE(&*o1 == &k);
|
||||
|
||||
k = 12;
|
||||
REQUIRE(*o1 == 12);
|
||||
|
||||
o1 = tl::nullopt;
|
||||
REQUIRE(!o1);
|
||||
|
||||
o1 = std::move(o2);
|
||||
REQUIRE(*o1 == 12);
|
||||
}
|
||||
|
107
tests/bases.cpp
Normal file
107
tests/bases.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "catch.hpp"
|
||||
#include "optional.hpp"
|
||||
|
||||
// Old versions of GCC don't have the correct trait names. Could fix them up if needs be.
|
||||
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
|
||||
!defined(__clang__))
|
||||
// nothing for now
|
||||
#else
|
||||
TEST_CASE("Triviality", "[bases.triviality]") {
|
||||
REQUIRE(std::is_trivially_copy_constructible<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_trivially_copy_assignable<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_trivially_move_constructible<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_trivially_move_assignable<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_trivially_destructible<tl::optional<int>>::value);
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&) = default;
|
||||
T(T&&) = default;
|
||||
T& operator=(const T&) = default;
|
||||
T& operator=(T&&) = default;
|
||||
~T() = default;
|
||||
};
|
||||
REQUIRE(std::is_trivially_copy_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_trivially_copy_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_trivially_move_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_trivially_move_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_trivially_destructible<tl::optional<T>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&){}
|
||||
T(T&&) {};
|
||||
T& operator=(const T&) {}
|
||||
T& operator=(T&&) {};
|
||||
~T(){}
|
||||
};
|
||||
REQUIRE(!std::is_trivially_copy_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_trivially_copy_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_trivially_move_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_trivially_move_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_trivially_destructible<tl::optional<T>>::value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("Deletion", "[bases.deletion]") {
|
||||
REQUIRE(std::is_copy_constructible<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_copy_assignable<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_move_constructible<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_move_assignable<tl::optional<int>>::value);
|
||||
REQUIRE(std::is_destructible<tl::optional<int>>::value);
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&) = default;
|
||||
T(T&&) = default;
|
||||
T& operator=(const T&) = default;
|
||||
T& operator=(T&&) = default;
|
||||
~T() = default;
|
||||
};
|
||||
REQUIRE(std::is_copy_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_copy_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_move_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_move_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_destructible<tl::optional<T>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&)=delete;
|
||||
T(T&&)=delete;
|
||||
T& operator=(const T&)=delete;
|
||||
T& operator=(T&&)=delete;
|
||||
};
|
||||
REQUIRE(!std::is_copy_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_copy_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_move_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_move_assignable<tl::optional<T>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&)=delete;
|
||||
T(T&&)=default;
|
||||
T& operator=(const T&)=delete;
|
||||
T& operator=(T&&)=default;
|
||||
};
|
||||
REQUIRE(!std::is_copy_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(!std::is_copy_assignable<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_move_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_move_assignable<tl::optional<T>>::value);
|
||||
}
|
||||
|
||||
{
|
||||
struct T {
|
||||
T(const T&)=default;
|
||||
T(T&&)=delete;
|
||||
T& operator=(const T&)=default;
|
||||
T& operator=(T&&)=delete;
|
||||
};
|
||||
REQUIRE(std::is_copy_constructible<tl::optional<T>>::value);
|
||||
REQUIRE(std::is_copy_assignable<tl::optional<T>>::value);
|
||||
}
|
||||
}
|
||||
#endif
|
17970
tests/catch.hpp
17970
tests/catch.hpp
File diff suppressed because it is too large
Load Diff
@ -2,30 +2,49 @@
|
||||
#include "optional.hpp"
|
||||
|
||||
TEST_CASE("Constructors", "[constructors]") {
|
||||
tl::optional<int> o1;
|
||||
REQUIRE(!o1);
|
||||
tl::optional<int> o1;
|
||||
REQUIRE(!o1);
|
||||
|
||||
tl::optional<int> o2 = tl::nullopt;
|
||||
REQUIRE(!o2);
|
||||
tl::optional<int> o2 = tl::nullopt;
|
||||
REQUIRE(!o2);
|
||||
|
||||
tl::optional<int> o3 = 42;
|
||||
REQUIRE(*o3 == 42);
|
||||
tl::optional<int> o3 = 42;
|
||||
REQUIRE(*o3 == 42);
|
||||
|
||||
tl::optional<int> o4 = o3;
|
||||
REQUIRE(*o4 == 42);
|
||||
tl::optional<int> o4 = o3;
|
||||
REQUIRE(*o4 == 42);
|
||||
|
||||
tl::optional<int> o5 = o1;
|
||||
REQUIRE(!o5);
|
||||
tl::optional<int> o5 = o1;
|
||||
REQUIRE(!o5);
|
||||
|
||||
tl::optional<int> o6 = std::move(o3);
|
||||
REQUIRE(*o6 == 42);
|
||||
tl::optional<int> o6 = std::move(o3);
|
||||
REQUIRE(*o6 == 42);
|
||||
|
||||
tl::optional<short> o7 = 42;
|
||||
REQUIRE(*o7 == 42);
|
||||
tl::optional<short> o7 = 42;
|
||||
REQUIRE(*o7 == 42);
|
||||
|
||||
tl::optional<int> o8 = o7;
|
||||
REQUIRE(*o8 == 42);
|
||||
tl::optional<int> o8 = o7;
|
||||
REQUIRE(*o8 == 42);
|
||||
|
||||
tl::optional<int> o9 = std::move(o7);
|
||||
REQUIRE(*o9 == 42);
|
||||
tl::optional<int> o9 = std::move(o7);
|
||||
REQUIRE(*o9 == 42);
|
||||
|
||||
{
|
||||
tl::optional<int &> o;
|
||||
REQUIRE(!o);
|
||||
|
||||
tl::optional<int &> oo = o;
|
||||
REQUIRE(!oo);
|
||||
}
|
||||
|
||||
{
|
||||
auto i = 42;
|
||||
tl::optional<int &> o = i;
|
||||
REQUIRE(o);
|
||||
REQUIRE(*o == 42);
|
||||
|
||||
tl::optional<int &> oo = o;
|
||||
REQUIRE(oo);
|
||||
REQUIRE(*oo == 42);
|
||||
}
|
||||
}
|
||||
|
@ -12,342 +12,261 @@ constexpr int get_int(int) { return 42; }
|
||||
TL_OPTIONAL_11_CONSTEXPR tl::optional<int> get_opt_int(int) { return 42; }
|
||||
|
||||
// What is Clang Format up to?!
|
||||
TEST_CASE("Monadic operations",
|
||||
"[monadic]"){SECTION("map"){// lhs is empty
|
||||
tl::optional<int> o1;
|
||||
auto o1r = o1.map([](int i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o1r), tl::optional<int>>::value));
|
||||
REQUIRE(!o1r);
|
||||
TEST_CASE("Monadic operations", "[monadic]") {
|
||||
SECTION("map") { // lhs is empty
|
||||
tl::optional<int> o1;
|
||||
auto o1r = o1.map([](int i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o1r), tl::optional<int>>::value));
|
||||
REQUIRE(!o1r);
|
||||
|
||||
// lhs has value
|
||||
tl::optional<int> o2 = 40;
|
||||
auto o2r = o2.map([](int i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o2r), tl::optional<int>>::value));
|
||||
REQUIRE(o2r.value() == 42);
|
||||
// lhs has value
|
||||
tl::optional<int> o2 = 40;
|
||||
auto o2r = o2.map([](int i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o2r), tl::optional<int>>::value));
|
||||
REQUIRE(o2r.value() == 42);
|
||||
|
||||
struct rval_call_map {
|
||||
double operator()(int) && { return 42.0; };
|
||||
};
|
||||
|
||||
// ensure that function object is forwarded
|
||||
tl::optional<int> o3 = 42;
|
||||
auto o3r = o3.map(rval_call_map{});
|
||||
STATIC_REQUIRE((std::is_same<decltype(o3r), tl::optional<double>>::value));
|
||||
REQUIRE(o3r.value() == 42);
|
||||
|
||||
// ensure that lhs is forwarded
|
||||
tl::optional<int> o4 = 40;
|
||||
auto o4r = std::move(o4).map([](int &&i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o4r), tl::optional<int>>::value));
|
||||
REQUIRE(o4r.value() == 42);
|
||||
|
||||
// ensure that lhs is const-propagated
|
||||
const tl::optional<int> o5 = 40;
|
||||
auto o5r = o5.map([](const int &i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o5r), tl::optional<int>>::value));
|
||||
REQUIRE(o5r.value() == 42);
|
||||
|
||||
// test applicative functor
|
||||
tl::optional<int> o6 = 40;
|
||||
auto f6 = tl::make_optional([](const int &i) { return i + 2; });
|
||||
auto o6r = o6.map(f6);
|
||||
STATIC_REQUIRE((std::is_same<decltype(o6r), tl::optional<int>>::value));
|
||||
REQUIRE(o6r.value() == 42);
|
||||
|
||||
// test void return
|
||||
tl::optional<int> o7 = 40;
|
||||
auto f7 = tl::make_optional([](const int &i) { return; });
|
||||
auto o7r = o7.map(f7);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(o7r), tl::optional<tl::monostate>>::value));
|
||||
REQUIRE(o6r.has_value());
|
||||
|
||||
// test each overload in turn
|
||||
tl::optional<int> o8 = 42;
|
||||
auto o8r = o8.map([](int) { return 42; });
|
||||
REQUIRE(*o8r == 42);
|
||||
|
||||
tl::optional<int> o9 = 42;
|
||||
auto o9r = o9.map([](int) { return; });
|
||||
REQUIRE(o9r);
|
||||
|
||||
tl::optional<int> o10 = 42;
|
||||
auto o10r = o10.map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(*o10r == 42);
|
||||
|
||||
tl::optional<int> o11 = 42;
|
||||
auto o11r = o11.map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(o11r);
|
||||
|
||||
tl::optional<int> o12 = 42;
|
||||
auto o12r = std::move(o12).map([](int) { return 42; });
|
||||
REQUIRE(*o12r == 42);
|
||||
|
||||
tl::optional<int> o13 = 42;
|
||||
auto o13r = std::move(o13).map([](int) { return; });
|
||||
REQUIRE(o13r);
|
||||
|
||||
tl::optional<int> o14 = 42;
|
||||
auto o14r = std::move(o14).map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(*o14r == 42);
|
||||
|
||||
tl::optional<int> o15 = 42;
|
||||
auto o15r = std::move(o15).map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(o15r);
|
||||
|
||||
const tl::optional<int> o16 = 42;
|
||||
auto o16r = o16.map([](int) { return 42; });
|
||||
REQUIRE(*o16r == 42);
|
||||
|
||||
const tl::optional<int> o17 = 42;
|
||||
auto o17r = o17.map([](int) { return; });
|
||||
REQUIRE(o17r);
|
||||
|
||||
const tl::optional<int> o18 = 42;
|
||||
auto o18r = o18.map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(*o18r == 42);
|
||||
|
||||
const tl::optional<int> o19 = 42;
|
||||
auto o19r = o19.map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(o19r);
|
||||
|
||||
const tl::optional<int> o20 = 42;
|
||||
auto o20r = std::move(o20).map([](int) { return 42; });
|
||||
REQUIRE(*o20r == 42);
|
||||
|
||||
const tl::optional<int> o21 = 42;
|
||||
auto o21r = std::move(o21).map([](int) { return; });
|
||||
REQUIRE(o21r);
|
||||
|
||||
const tl::optional<int> o22 = 42;
|
||||
auto o22r = std::move(o22).map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(*o22r == 42);
|
||||
|
||||
const tl::optional<int> o23 = 42;
|
||||
auto o23r = std::move(o23).map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(o23r);
|
||||
|
||||
tl::optional<int> o24 = tl::nullopt;
|
||||
auto o24r = o24.map([](int) { return 42; });
|
||||
REQUIRE(!o24r);
|
||||
|
||||
tl::optional<int> o25 = tl::nullopt;
|
||||
auto o25r = o25.map([](int) { return; });
|
||||
REQUIRE(!o25r);
|
||||
|
||||
tl::optional<int> o26 = tl::nullopt;
|
||||
auto o26r = o26.map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(!o26r);
|
||||
|
||||
tl::optional<int> o27 = tl::nullopt;
|
||||
auto o27r = o27.map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(!o27r);
|
||||
|
||||
tl::optional<int> o28 = tl::nullopt;
|
||||
auto o28r = std::move(o28).map([](int) { return 42; });
|
||||
REQUIRE(!o28r);
|
||||
|
||||
tl::optional<int> o29 = tl::nullopt;
|
||||
auto o29r = std::move(o29).map([](int) { return; });
|
||||
REQUIRE(!o29r);
|
||||
|
||||
tl::optional<int> o30 = tl::nullopt;
|
||||
auto o30r = std::move(o30).map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(!o30r);
|
||||
|
||||
tl::optional<int> o31 = tl::nullopt;
|
||||
auto o31r = std::move(o31).map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(!o31r);
|
||||
|
||||
const tl::optional<int> o32 = tl::nullopt;
|
||||
auto o32r = o32.map([](int) { return 42; });
|
||||
REQUIRE(!o32r);
|
||||
|
||||
const tl::optional<int> o33 = tl::nullopt;
|
||||
auto o33r = o33.map([](int) { return; });
|
||||
REQUIRE(!o33r);
|
||||
|
||||
const tl::optional<int> o34 = tl::nullopt;
|
||||
auto o34r = o34.map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(!o34r);
|
||||
|
||||
const tl::optional<int> o35 = tl::nullopt;
|
||||
auto o35r = o35.map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(!o35r);
|
||||
|
||||
const tl::optional<int> o36 = tl::nullopt;
|
||||
auto o36r = std::move(o36).map([](int) { return 42; });
|
||||
REQUIRE(!o36r);
|
||||
|
||||
const tl::optional<int> o37 = tl::nullopt;
|
||||
auto o37r = std::move(o37).map([](int) { return; });
|
||||
REQUIRE(!o37r);
|
||||
|
||||
const tl::optional<int> o38 = tl::nullopt;
|
||||
auto o38r = std::move(o38).map(tl::make_optional([](int) { return 42; }));
|
||||
REQUIRE(!o38r);
|
||||
|
||||
const tl::optional<int> o39 = tl::nullopt;
|
||||
auto o39r = std::move(o39).map(tl::make_optional([](int) { return; }));
|
||||
REQUIRE(!o39r);
|
||||
}
|
||||
|
||||
SECTION("map constexpr") {
|
||||
#if !defined(_MSC_VER) && !defined(TL_OPTIONAL_GCC49)
|
||||
// test each overload in turn
|
||||
constexpr tl::optional<int> o16 = 42;
|
||||
constexpr auto o16r = o16.map(get_int);
|
||||
STATIC_REQUIRE(*o16r == 42);
|
||||
|
||||
constexpr tl::optional<int> o18 = 42;
|
||||
constexpr auto opt_int = tl::make_optional(get_int);
|
||||
constexpr auto o18r = o18.map(opt_int);
|
||||
STATIC_REQUIRE(*o18r == 42);
|
||||
|
||||
constexpr tl::optional<int> o20 = 42;
|
||||
constexpr auto o20r = std::move(o20).map(get_int);
|
||||
STATIC_REQUIRE(*o20r == 42);
|
||||
|
||||
constexpr tl::optional<int> o22 = 42;
|
||||
constexpr auto o22r = std::move(o22).map(opt_int);
|
||||
STATIC_REQUIRE(*o22r == 42);
|
||||
|
||||
constexpr tl::optional<int> o32 = tl::nullopt;
|
||||
constexpr auto o32r = o32.map(get_int);
|
||||
STATIC_REQUIRE(!o32r);
|
||||
|
||||
constexpr tl::optional<int> o34 = tl::nullopt;
|
||||
constexpr auto o34r = o34.map(opt_int);
|
||||
STATIC_REQUIRE(!o34r);
|
||||
|
||||
constexpr tl::optional<int> o36 = tl::nullopt;
|
||||
constexpr auto o36r = std::move(o36).map(get_int);
|
||||
STATIC_REQUIRE(!o36r);
|
||||
|
||||
constexpr tl::optional<int> o38 = tl::nullopt;
|
||||
constexpr auto o38r = std::move(o38).map(opt_int);
|
||||
STATIC_REQUIRE(!o38r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("and_then") {
|
||||
|
||||
// lhs is empty
|
||||
tl::optional<int> o1;
|
||||
auto o1r = o1.and_then([](int i) { return tl::optional<float>{42}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o1r), tl::optional<float>>::value));
|
||||
REQUIRE(!o1r);
|
||||
|
||||
// lhs has value
|
||||
tl::optional<int> o2 = 12;
|
||||
auto o2r = o2.and_then([](int i) { return tl::optional<float>{42}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o2r), tl::optional<float>>::value));
|
||||
REQUIRE(o2r.value() == 42.f);
|
||||
|
||||
// lhs is empty, rhs returns empty
|
||||
tl::optional<int> o3;
|
||||
auto o3r = o3.and_then([](int i) { return tl::optional<float>{}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o3r), tl::optional<float>>::value));
|
||||
REQUIRE(!o3r);
|
||||
|
||||
// rhs returns empty
|
||||
tl::optional<int> o4 = 12;
|
||||
auto o4r = o4.and_then([](int i) { return tl::optional<float>{}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o4r), tl::optional<float>>::value));
|
||||
REQUIRE(!o4r);
|
||||
|
||||
struct rval_call_and_then {
|
||||
tl::optional<double> operator()(int) && {
|
||||
return tl::optional<double>(42.0);
|
||||
struct rval_call_map {
|
||||
double operator()(int) && { return 42.0; };
|
||||
};
|
||||
};
|
||||
|
||||
// ensure that function object is forwarded
|
||||
tl::optional<int> o5 = 42;
|
||||
auto o5r = o5.and_then(rval_call_and_then{});
|
||||
STATIC_REQUIRE((std::is_same<decltype(o5r), tl::optional<double>>::value));
|
||||
REQUIRE(o5r.value() == 42);
|
||||
// ensure that function object is forwarded
|
||||
tl::optional<int> o3 = 42;
|
||||
auto o3r = o3.map(rval_call_map{});
|
||||
STATIC_REQUIRE((std::is_same<decltype(o3r), tl::optional<double>>::value));
|
||||
REQUIRE(o3r.value() == 42);
|
||||
|
||||
// ensure that lhs is forwarded
|
||||
tl::optional<int> o6 = 42;
|
||||
auto o6r =
|
||||
std::move(o6).and_then([](int &&i) { return tl::optional<double>(i); });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o6r), tl::optional<double>>::value));
|
||||
REQUIRE(o6r.value() == 42);
|
||||
// ensure that lhs is forwarded
|
||||
tl::optional<int> o4 = 40;
|
||||
auto o4r = std::move(o4).map([](int &&i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o4r), tl::optional<int>>::value));
|
||||
REQUIRE(o4r.value() == 42);
|
||||
|
||||
// ensure that function object is const-propagated
|
||||
const tl::optional<int> o7 = 42;
|
||||
auto o7r = o7.and_then([](const int &i) { return tl::optional<double>(i); });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o7r), tl::optional<double>>::value));
|
||||
REQUIRE(o7r.value() == 42);
|
||||
// ensure that lhs is const-propagated
|
||||
const tl::optional<int> o5 = 40;
|
||||
auto o5r = o5.map([](const int &i) { return i + 2; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o5r), tl::optional<int>>::value));
|
||||
REQUIRE(o5r.value() == 42);
|
||||
|
||||
// test each overload in turn
|
||||
tl::optional<int> o8 = 42;
|
||||
auto o8r = o8.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o8r == 42);
|
||||
// test void return
|
||||
tl::optional<int> o7 = 40;
|
||||
auto f7 = [](const int &i) { return; };
|
||||
auto o7r = o7.map(f7);
|
||||
STATIC_REQUIRE(
|
||||
(std::is_same<decltype(o7r), tl::optional<tl::monostate>>::value));
|
||||
REQUIRE(o7r.has_value());
|
||||
|
||||
tl::optional<int> o9 = 42;
|
||||
auto o9r =
|
||||
std::move(o9).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o9r == 42);
|
||||
// test each overload in turn
|
||||
tl::optional<int> o8 = 42;
|
||||
auto o8r = o8.map([](int) { return 42; });
|
||||
REQUIRE(*o8r == 42);
|
||||
|
||||
const tl::optional<int> o10 = 42;
|
||||
auto o10r = o10.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o10r == 42);
|
||||
tl::optional<int> o9 = 42;
|
||||
auto o9r = o9.map([](int) { return; });
|
||||
REQUIRE(o9r);
|
||||
|
||||
const tl::optional<int> o11 = 42;
|
||||
auto o11r =
|
||||
std::move(o11).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o11r == 42);
|
||||
tl::optional<int> o12 = 42;
|
||||
auto o12r = std::move(o12).map([](int) { return 42; });
|
||||
REQUIRE(*o12r == 42);
|
||||
|
||||
tl::optional<int> o16 = tl::nullopt;
|
||||
auto o16r = o16.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o16r);
|
||||
tl::optional<int> o13 = 42;
|
||||
auto o13r = std::move(o13).map([](int) { return; });
|
||||
REQUIRE(o13r);
|
||||
|
||||
tl::optional<int> o17 = tl::nullopt;
|
||||
auto o17r =
|
||||
std::move(o17).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o17r);
|
||||
const tl::optional<int> o16 = 42;
|
||||
auto o16r = o16.map([](int) { return 42; });
|
||||
REQUIRE(*o16r == 42);
|
||||
|
||||
const tl::optional<int> o18 = tl::nullopt;
|
||||
auto o18r = o18.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o18r);
|
||||
const tl::optional<int> o17 = 42;
|
||||
auto o17r = o17.map([](int) { return; });
|
||||
REQUIRE(o17r);
|
||||
|
||||
const tl::optional<int> o19 = tl::nullopt;
|
||||
auto o19r =
|
||||
std::move(o19).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o19r);
|
||||
}
|
||||
const tl::optional<int> o20 = 42;
|
||||
auto o20r = std::move(o20).map([](int) { return 42; });
|
||||
REQUIRE(*o20r == 42);
|
||||
|
||||
SECTION("constexpr and_then") {
|
||||
const tl::optional<int> o21 = 42;
|
||||
auto o21r = std::move(o21).map([](int) { return; });
|
||||
REQUIRE(o21r);
|
||||
|
||||
tl::optional<int> o24 = tl::nullopt;
|
||||
auto o24r = o24.map([](int) { return 42; });
|
||||
REQUIRE(!o24r);
|
||||
|
||||
tl::optional<int> o25 = tl::nullopt;
|
||||
auto o25r = o25.map([](int) { return; });
|
||||
REQUIRE(!o25r);
|
||||
|
||||
tl::optional<int> o28 = tl::nullopt;
|
||||
auto o28r = std::move(o28).map([](int) { return 42; });
|
||||
REQUIRE(!o28r);
|
||||
|
||||
tl::optional<int> o29 = tl::nullopt;
|
||||
auto o29r = std::move(o29).map([](int) { return; });
|
||||
REQUIRE(!o29r);
|
||||
|
||||
const tl::optional<int> o32 = tl::nullopt;
|
||||
auto o32r = o32.map([](int) { return 42; });
|
||||
REQUIRE(!o32r);
|
||||
|
||||
const tl::optional<int> o33 = tl::nullopt;
|
||||
auto o33r = o33.map([](int) { return; });
|
||||
REQUIRE(!o33r);
|
||||
|
||||
const tl::optional<int> o36 = tl::nullopt;
|
||||
auto o36r = std::move(o36).map([](int) { return 42; });
|
||||
REQUIRE(!o36r);
|
||||
|
||||
const tl::optional<int> o37 = tl::nullopt;
|
||||
auto o37r = std::move(o37).map([](int) { return; });
|
||||
REQUIRE(!o37r);
|
||||
|
||||
// callable which returns a reference
|
||||
tl::optional<int> o38 = 42;
|
||||
auto o38r = o38.map([](int &i) -> const int & { return i; });
|
||||
REQUIRE(o38r);
|
||||
REQUIRE(*o38r == 42);
|
||||
}
|
||||
|
||||
SECTION("map constexpr") {
|
||||
#if !defined(_MSC_VER) && !defined(TL_OPTIONAL_GCC49)
|
||||
constexpr tl::optional<int> o10 = 42;
|
||||
constexpr auto o10r = o10.and_then(get_opt_int);
|
||||
REQUIRE(*o10r == 42);
|
||||
// test each overload in turn
|
||||
constexpr tl::optional<int> o16 = 42;
|
||||
constexpr auto o16r = o16.map(get_int);
|
||||
STATIC_REQUIRE(*o16r == 42);
|
||||
|
||||
constexpr tl::optional<int> o11 = 42;
|
||||
constexpr auto o11r = std::move(o11).and_then(get_opt_int);
|
||||
REQUIRE(*o11r == 42);
|
||||
constexpr tl::optional<int> o20 = 42;
|
||||
constexpr auto o20r = std::move(o20).map(get_int);
|
||||
STATIC_REQUIRE(*o20r == 42);
|
||||
|
||||
constexpr tl::optional<int> o18 = tl::nullopt;
|
||||
constexpr auto o18r = o18.and_then(get_opt_int);
|
||||
REQUIRE(!o18r);
|
||||
|
||||
constexpr tl::optional<int> o19 = tl::nullopt;
|
||||
constexpr auto o19r = std::move(o19).and_then(get_opt_int);
|
||||
REQUIRE(!o19r);
|
||||
constexpr tl::optional<int> o32 = tl::nullopt;
|
||||
constexpr auto o32r = o32.map(get_int);
|
||||
STATIC_REQUIRE(!o32r);
|
||||
constexpr tl::optional<int> o36 = tl::nullopt;
|
||||
constexpr auto o36r = std::move(o36).map(get_int);
|
||||
STATIC_REQUIRE(!o36r);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("or else") {
|
||||
SECTION("and_then") {
|
||||
|
||||
// lhs is empty
|
||||
tl::optional<int> o1;
|
||||
auto o1r = o1.and_then([](int i) { return tl::optional<float>{42}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o1r), tl::optional<float>>::value));
|
||||
REQUIRE(!o1r);
|
||||
|
||||
// lhs has value
|
||||
tl::optional<int> o2 = 12;
|
||||
auto o2r = o2.and_then([](int i) { return tl::optional<float>{42}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o2r), tl::optional<float>>::value));
|
||||
REQUIRE(o2r.value() == 42.f);
|
||||
|
||||
// lhs is empty, rhs returns empty
|
||||
tl::optional<int> o3;
|
||||
auto o3r = o3.and_then([](int i) { return tl::optional<float>{}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o3r), tl::optional<float>>::value));
|
||||
REQUIRE(!o3r);
|
||||
|
||||
// rhs returns empty
|
||||
tl::optional<int> o4 = 12;
|
||||
auto o4r = o4.and_then([](int i) { return tl::optional<float>{}; });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o4r), tl::optional<float>>::value));
|
||||
REQUIRE(!o4r);
|
||||
|
||||
struct rval_call_and_then {
|
||||
tl::optional<double> operator()(int) && {
|
||||
return tl::optional<double>(42.0);
|
||||
};
|
||||
};
|
||||
|
||||
// ensure that function object is forwarded
|
||||
tl::optional<int> o5 = 42;
|
||||
auto o5r = o5.and_then(rval_call_and_then{});
|
||||
STATIC_REQUIRE((std::is_same<decltype(o5r), tl::optional<double>>::value));
|
||||
REQUIRE(o5r.value() == 42);
|
||||
|
||||
// ensure that lhs is forwarded
|
||||
tl::optional<int> o6 = 42;
|
||||
auto o6r =
|
||||
std::move(o6).and_then([](int &&i) { return tl::optional<double>(i); });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o6r), tl::optional<double>>::value));
|
||||
REQUIRE(o6r.value() == 42);
|
||||
|
||||
// ensure that function object is const-propagated
|
||||
const tl::optional<int> o7 = 42;
|
||||
auto o7r =
|
||||
o7.and_then([](const int &i) { return tl::optional<double>(i); });
|
||||
STATIC_REQUIRE((std::is_same<decltype(o7r), tl::optional<double>>::value));
|
||||
REQUIRE(o7r.value() == 42);
|
||||
|
||||
// test each overload in turn
|
||||
tl::optional<int> o8 = 42;
|
||||
auto o8r = o8.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o8r == 42);
|
||||
|
||||
tl::optional<int> o9 = 42;
|
||||
auto o9r =
|
||||
std::move(o9).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o9r == 42);
|
||||
|
||||
const tl::optional<int> o10 = 42;
|
||||
auto o10r = o10.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o10r == 42);
|
||||
|
||||
const tl::optional<int> o11 = 42;
|
||||
auto o11r =
|
||||
std::move(o11).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(*o11r == 42);
|
||||
|
||||
tl::optional<int> o16 = tl::nullopt;
|
||||
auto o16r = o16.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o16r);
|
||||
|
||||
tl::optional<int> o17 = tl::nullopt;
|
||||
auto o17r =
|
||||
std::move(o17).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o17r);
|
||||
|
||||
const tl::optional<int> o18 = tl::nullopt;
|
||||
auto o18r = o18.and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o18r);
|
||||
|
||||
const tl::optional<int> o19 = tl::nullopt;
|
||||
auto o19r =
|
||||
std::move(o19).and_then([](int i) { return tl::make_optional(42); });
|
||||
REQUIRE(!o19r);
|
||||
}
|
||||
|
||||
SECTION("constexpr and_then") {
|
||||
#if !defined(_MSC_VER) && !defined(TL_OPTIONAL_GCC49)
|
||||
|
||||
constexpr tl::optional<int> o10 = 42;
|
||||
constexpr auto o10r = o10.and_then(get_opt_int);
|
||||
REQUIRE(*o10r == 42);
|
||||
|
||||
constexpr tl::optional<int> o11 = 42;
|
||||
constexpr auto o11r = std::move(o11).and_then(get_opt_int);
|
||||
REQUIRE(*o11r == 42);
|
||||
|
||||
constexpr tl::optional<int> o18 = tl::nullopt;
|
||||
constexpr auto o18r = o18.and_then(get_opt_int);
|
||||
REQUIRE(!o18r);
|
||||
|
||||
constexpr tl::optional<int> o19 = tl::nullopt;
|
||||
constexpr auto o19r = std::move(o19).and_then(get_opt_int);
|
||||
REQUIRE(!o19r);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("or else") {
|
||||
tl::optional<int> o1 = 42;
|
||||
REQUIRE(*(o1.or_else([] { return tl::make_optional(13); })) == 42);
|
||||
|
||||
tl::optional<int> o2;
|
||||
REQUIRE(*(o2.or_else([] { return tl::make_optional(13); })) == 13);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("disjunction") {
|
||||
SECTION("disjunction") {
|
||||
tl::optional<int> o1 = 42;
|
||||
tl::optional<int> o2 = 12;
|
||||
tl::optional<int> o3;
|
||||
@ -358,37 +277,37 @@ SECTION("disjunction") {
|
||||
REQUIRE(*o2.disjunction(o3) == 12);
|
||||
REQUIRE(*o3.disjunction(o1) == 42);
|
||||
REQUIRE(*o3.disjunction(o2) == 12);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("conjunction") {
|
||||
SECTION("conjunction") {
|
||||
tl::optional<int> o1 = 42;
|
||||
REQUIRE(*o1.conjunction(42.0) == 42.0);
|
||||
REQUIRE(*o1.conjunction(std::string{"hello"}) == std::string{"hello"});
|
||||
REQUIRE(!o1.conjunction(tl::nullopt));
|
||||
|
||||
tl::optional<int> o2;
|
||||
REQUIRE(!o2.conjunction(42.0));
|
||||
REQUIRE(!o2.conjunction(std::string{"hello"}));
|
||||
REQUIRE(!o2.conjunction(tl::nullopt));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("map_or") {
|
||||
SECTION("map_or") {
|
||||
tl::optional<int> o1 = 21;
|
||||
REQUIRE((o1.map_or([](int x) { return x * 2; }, 13)) == 42);
|
||||
|
||||
tl::optional<int> o2;
|
||||
REQUIRE((o2.map_or([](int x) { return x * 2; }, 13)) == 13);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("map_or_else") {
|
||||
SECTION("map_or_else") {
|
||||
tl::optional<int> o1 = 21;
|
||||
REQUIRE((o1.map_or_else([](int x) { return x * 2; }, []{return 13;})) == 42);
|
||||
REQUIRE((o1.map_or_else([](int x) { return x * 2; }, [] { return 13; })) ==
|
||||
42);
|
||||
|
||||
tl::optional<int> o2;
|
||||
REQUIRE((o2.map_or_else([](int x) { return x * 2; }, []{return 13;})) == 13);
|
||||
}
|
||||
REQUIRE((o2.map_or_else([](int x) { return x * 2; }, [] { return 13; })) ==
|
||||
13);
|
||||
}
|
||||
|
||||
SECTION("take") {
|
||||
SECTION("take") {
|
||||
tl::optional<int> o1 = 42;
|
||||
REQUIRE(*o1.take() == 42);
|
||||
REQUIRE(!o1);
|
||||
@ -396,6 +315,28 @@ SECTION("take") {
|
||||
tl::optional<int> o2;
|
||||
REQUIRE(!o2.take());
|
||||
REQUIRE(!o2);
|
||||
}
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
struct foo {
|
||||
void non_const() {}
|
||||
};
|
||||
|
||||
#if defined(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
|
||||
!defined(TL_OPTIONAL_GCC54)
|
||||
SECTION("Issue #1") {
|
||||
tl::optional<foo> f = foo{};
|
||||
auto l = [](auto &&x) { x.non_const(); };
|
||||
f.map(l);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct overloaded {
|
||||
tl::optional<int> operator()(foo &) { return 0; }
|
||||
tl::optional<std::string> operator()(const foo &) { return ""; }
|
||||
};
|
||||
|
||||
SECTION("Issue #2") {
|
||||
tl::optional<foo> f = foo{};
|
||||
auto x = f.and_then(overloaded{});
|
||||
}
|
||||
};
|
||||
|
@ -37,4 +37,10 @@ TEST_CASE("Make optional", "[make_optional]") {
|
||||
REQUIRE(o5->v[1] == 1);
|
||||
REQUIRE(std::get<0>(o5->t) == 2);
|
||||
REQUIRE(std::get<1>(o5->t) == 3);
|
||||
|
||||
auto i = 42;
|
||||
auto o6 = tl::make_optional<int&>(i);
|
||||
REQUIRE((std::is_same<decltype(o6), tl::optional<int&>>::value));
|
||||
REQUIRE(o6);
|
||||
REQUIRE(*o6 == 42);
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ TEST_CASE("Noexcept", "[noexcept]") {
|
||||
using nothrow_opt = tl::optional<nothrow_move>;
|
||||
using throw_opt = tl::optional<throw_move>;
|
||||
|
||||
REQUIRE(noexcept(nothrow_opt{std::declval<nothrow_opt>()}));
|
||||
REQUIRE(!noexcept(throw_opt{std::declval<throw_opt>()}));
|
||||
REQUIRE(std::is_nothrow_move_constructible<nothrow_opt>::value);
|
||||
REQUIRE(!std::is_nothrow_move_constructible<throw_opt>::value);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
2308
tl/optional.hpp
Normal file
2308
tl/optional.hpp
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user