146 Commits

Author SHA1 Message Date
5c42d8fa3b Added library.json for platformio 2020-09-22 16:07:07 +02:00
0dfc7b4e41 Use add_library for subdirectory usage instead of add_executable 2019-11-11 10:56:36 +00:00
8177b93e7f Fix Travis for C++17 Clang builds 2019-10-25 14:40:28 +01:00
352b529889 Merge pull request #36 from slurps-mad-rips/cmake-revamp
Revamp CMake files to be more understandable and correct
2019-10-25 14:37:01 +01:00
e165e3554c Merge pull request #35 from IDragnev/fix_readme
Fix mistakes in README.md
2019-09-21 21:34:15 +01:00
c325c63b17 fixup! fixup! 🎨 Cleanup include path for catch2 2019-09-17 10:18:56 -07:00
dcebd5897f fixup! 🎨 Cleanup include path for catch2 2019-09-17 10:14:58 -07:00
54f7f970bf 🎨 Cleanup include path for catch2
 Add basic .deb generation support
WiX and RPM support is still needed for verification

⬆️ Upgrade minimum CMake version to 3.14
⬆️ Upgrade Catch to Catch v2.9.2
📌 Pin Catch to v2.9.1

👷 Update .travis.yml build matrix
👷 Update .appveyor build script

 Update tests to be separated by file
2019-09-17 09:59:36 -07:00
2673f3f9b3 Fix mistakes in README.md 2019-09-16 19:56:05 +03:00
83a0b49e5e Merge pull request #34 from denizevrenci/fix_emplace_on_ref
Fix implementation of optional<T&>::emplace()
2019-07-08 13:28:30 +01:00
ce266d5280 Add test 2019-07-08 20:07:06 +09:00
b074bee409 Fix implementation of optional<T&>::emplace() 2019-07-08 20:07:06 +09:00
084a9001f4 Add missing noexcept specifications to methods of optional<T&> 2019-07-08 20:07:06 +09:00
5c4876059c Update header 2019-06-25 12:38:17 +01:00
71a8031dd2 Fix swap include path 2019-06-25 11:51:38 +01:00
a2650823a0 Merge pull request #27 from TartanLlama/cmake_love
Do CMake properly
2019-06-25 11:18:19 +01:00
aef62df93e Merge branch 'master' into cmake_love 2019-06-25 11:17:40 +01:00
359499d904 Use Xenial repos 2019-06-25 10:52:08 +01:00
9839b761e0 Tidy traits 2019-06-25 10:47:46 +01:00
d613d3422d Merge pull request #28 from glynos/swap_has_value_fix
Added tests for bug when swapping value/null-value and null-value value
2019-06-25 10:27:55 +01:00
3cfcb3ff2d Use Xenial on Travis instead of Trusty 2019-06-25 10:07:25 +01:00
d7356bb01c Use FetchContent 2019-06-25 09:47:19 +01:00
8fbb0262a1 Added tests for bug when swapping value/null-value and null-value value 2019-05-31 21:22:29 +02:00
6ce85550f3 Do CMake properly 2019-05-01 13:23:30 +01:00
53697d4a36 Make take always move
Fixes #23
2019-05-01 09:40:47 +01:00
c3752db7e8 Remove in-source docs 2019-05-01 09:39:50 +01:00
4b22ab1ba6 Add transform tests 2019-05-01 09:39:41 +01:00
06032ebdae Add transform 2019-05-01 09:19:31 +01:00
2d42ed8304 Update README.md 2019-04-30 11:59:11 +01:00
b8f4ca1169 Update README.md 2019-04-30 11:58:50 +01:00
0aa68c8d47 Merge pull request #25 from TartanLlama/swappable
Remove old docs
2019-04-30 11:56:50 +01:00
fada9fae5f Merge branch 'master' into swappable 2019-04-29 16:59:35 +01:00
8be5c63925 Remove old docs 2019-04-29 16:58:30 +01:00
7de669d9c7 Update README.md 2019-04-29 14:58:31 +01:00
f632a98e84 Merge pull request #24 from TartanLlama/swappable
Swappable
2019-04-26 13:45:14 +01:00
9399c30330 Correct MSC_VER check 2019-02-19 14:58:36 +00:00
d2c6fa68c7 Move is_swappable implementation, correct MSC_VER check 2019-02-19 14:58:09 +00:00
dff20e9c9f Merge pull request #22 from ThePhD/patch-1
[ constructors ] prevent empty optional access
2019-02-19 11:00:02 +00:00
7ef0154330 Use correct is_swappable implementation for VS2017+ 2019-02-19 10:57:43 +00:00
4304148904 Turn docs off by default
Fixes #20
2019-02-19 09:51:23 +00:00
1de2f2a49c [ constructors ] prevent empty optional access
optional types being taken in were forwarding their values without checking, resulting in segfaults on optional<U> -> optional<T> conversions. This fixes those problems in the constructors.
2019-02-13 09:00:07 -05:00
5d3d6c399a Add email address
Fixes #18
2019-02-11 11:38:24 +00:00
1baad184f0 Merge pull request #17 from johvik/patch-1
Return value() in noexcept emplace
2019-01-23 08:45:04 +00:00
c194f73a07 Return value() in noexcept emplace 2019-01-23 08:38:31 +01:00
47b120fd53 Merge pull request #16 from DecoyRS/patch-1
Misaligned template specifiers
2018-11-23 08:35:39 +00:00
99b2a15863 Misaligned template specifiers
Tried to compile with CLion + CLang + WSL, got error pointing to this place. Looks like a copy-paste error )
2018-11-22 22:49:33 +03:00
dc02563d7b Update version 2018-11-09 15:34:16 +00:00
3449fbc904 Fix #15 2018-10-12 13:34:03 +01:00
b53059c63d Fix macro issue 2018-09-06 09:34:05 +01:00
25f8f28a9a Workaround MSVC2015 bug 2018-09-03 14:55:54 +01:00
6c5e6d6477 More Clang fixes 2018-09-03 14:30:07 +01:00
4d5453bc56 Add missing define 2018-09-03 13:49:56 +01:00
068d3db664 Workaround libcxx issue 2018-09-03 12:10:22 +01:00
fd6c65e7f9 Merge branch 'master' of github.com:TartanLlama/optional 2018-09-03 09:09:57 +01:00
aecb8fe6db Fix #14 2018-09-03 09:09:47 +01:00
0d449821ca Merge pull request #13 from mortenfyhn/master
Add syntax highlighting to readme
2018-08-31 15:25:41 +01:00
6738107bae Add syntax highlighting to readme 2018-08-31 16:15:55 +02:00
8b1c3fb67f Fix the other bad comment 2018-08-22 15:50:43 +01:00
dd8ab0232e Fix trivially destructible comment 2018-08-22 15:22:43 +01:00
dc129ecf10 Only include vector workaround if vector is included 2018-08-22 15:22:16 +01:00
bf0efe1625 Add vector workaround mutex 2018-08-22 15:21:31 +01:00
9df8d1be39 Support std::vector of non-copyable types 2018-08-14 09:56:31 +01:00
35e4c6e889 Remove unneeded file 2018-07-25 16:03:01 +01:00
aa74eb709f Add emplace test 2018-07-11 14:32:25 +01:00
5dd9ed7e2c Merge pull request #10 from kbenzie/cmake_subdirectory
Play nice with CMake add_subdirectory
2018-06-08 10:51:01 +01:00
48d70a1604 Play nice with CMake add_subdirectory
Enable use of `tl::optional<T>` purely as a library with CMake's
`add_subdirectory`. The default configuration works are before.

* `OPTIONAL_ENABLE_TESTS` make building tests optional, enabled by default
* `OPTIONAL_ENABLE_DOCS` make building documentation optional, enabled by default
2018-06-08 10:45:19 +01:00
c8a6658f9f Remove GCC5.5 from test 2018-06-07 09:23:52 +01:00
04b817f0d3 Correct GCC5.5 macro 2018-06-07 09:05:39 +01:00
6e8235c085 Remove GCC5.5 from constexpr tests 2018-06-07 08:54:43 +01:00
b3b2715a95 Remove GCC5.5 from constexpr tests 2018-06-07 08:28:29 +01:00
90b00674dd More C++14 void fixes 2018-06-06 13:54:12 +01:00
e0a542f960 More GCC 5.5 fixes 2018-06-06 11:24:10 +01:00
b72cc392b6 Typo 2018-06-06 11:14:36 +01:00
9f01853678 Update readme 2018-06-06 10:46:34 +01:00
d9d1a54abc Test GCC 5.5 2018-06-06 10:27:54 +01:00
0dd57d441c Merge branch 'master' of github.com:TartanLlama/optional 2018-06-06 10:27:13 +01:00
9a1b033113 Fix GCC 5.5 2018-06-06 10:27:08 +01:00
d67e7c2eac Merge pull request #9 from rollbear/master
'optional<T&>::and_then(F&& f) &&' calls f with lvalue reference
2018-06-04 22:34:48 +01:00
e8b28f2e34 and the obligatory fixup for C++-11 :-) 2018-06-03 15:01:57 +02:00
5143f9577a 'optional<T&>::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<int&>{i}.and_then([](int& r){return optional<int&>{++r});

The optional r-value still refers to 'i', which is not an r-value.
2018-06-03 12:09:17 +02:00
f82f78b5b6 Update supported compilers 2018-05-28 22:22:28 +01:00
3a20e3f8cd Update travis compilers 2018-05-28 22:08:15 +01:00
779cf10329 Qualify call to detail::invoke so that std::invoke isn't picked up due to ADL in C++17 2018-05-28 21:46:58 +01:00
effc941116 Fix warnings 2018-04-11 15:54:58 +01:00
94b7563fdf Merge branch 'master' of github.com:TartanLlama/optional 2018-04-11 15:53:11 +01:00
d8973a6524 Fix #8 2018-04-11 15:53:01 +01:00
ac8134265c Merge pull request #6 from basiliscos/add-return
Add return
2018-03-19 08:13:38 +00:00
10e687e188 Add return 2018-03-09 22:46:02 +03:00
74a422b824 Rename map_impl 2018-03-05 11:04:09 +00:00
dccbc0b23e C++11 fixes 2018-02-23 09:34:05 +00:00
27b2163d10 Merge branch 'reference' 2018-02-23 09:25:42 +00:00
3452cc1c8c Fix macro 2018-02-23 09:23:53 +00:00
2ab4f77498 Test C++11 mode 2018-02-23 09:17:53 +00:00
cb52a3b744 Remove rvalue observers for optional<T&> 2018-02-11 09:52:19 +00:00
d7ec1da407 Fix map for reference types 2018-02-11 09:40:01 +00:00
4bde006cb5 Fix map for reference types 2018-02-11 09:32:35 +00:00
14cfd77197 Rename type trait macros 2018-01-14 07:38:34 +00:00
57d659daf5 Merge pull request #3 from TartanLlama/reference
Support optional references
2017-12-18 10:56:40 +00:00
883df6b427 Publish docs 2017-12-18 10:55:36 +00:00
f621ca663e Standardese 2017-12-18 10:55:12 +00:00
8b408f5fd6 More docs 2017-12-18 10:51:48 +00:00
632bc4e1ad Update readme 2017-12-18 10:21:46 +00:00
717027db9b More tests 2017-12-18 10:10:11 +00:00
8c3f042b12 More tests 2017-12-18 09:56:36 +00:00
c4e3b3ee14 Get references compiling, initial tests 2017-12-14 14:53:35 +00:00
bdaa41ce8c Initial support for references 2017-12-13 16:03:01 +00:00
e589ae4321 Add static asserts 2017-12-13 11:34:33 +00:00
6c73b8113f Bases fix 2017-12-13 09:13:05 +00:00
32656c4556 Fix CMake 2017-12-05 19:53:49 +00:00
b3dc6d1a52 Put header in 'tl' folder 2017-12-05 19:51:42 +00:00
247677394f Support mapping functions which return references 2017-12-05 19:51:20 +00:00
5a3f094ec7 Update docs 2017-11-27 15:12:44 +00:00
26c00afe27 Fix bases test 2017-11-27 15:08:34 +00:00
4308924a38 Fix GCC issues 2017-11-27 14:51:32 +00:00
6c4178a947 More testing 2017-11-27 14:36:59 +00:00
c67aaff948 Update mutexes 2017-11-27 12:24:47 +00:00
b9486ce776 Clang format, support cohabitation with tl::expected 2017-11-16 11:17:26 +00:00
a1d27b2aba Merge branch 'master' of github.com:TartanLlama/monadic-optional-new 2017-11-06 08:51:46 +00:00
d9ce8cf5c5 Update readme 2017-11-06 08:51:33 +00:00
e62348c128 More testing 2017-11-05 20:31:18 +00:00
39030e6a00 Fix ifdef 2017-11-03 14:29:35 +00:00
4d5f9bd785 Fix ifdef 2017-11-03 14:29:21 +00:00
f6802daada Clang format 2017-11-03 14:29:02 +00:00
59cf950873 Upgrade to Catch 2 2017-11-03 14:19:44 +00:00
e4e32ea56d Fix assignment chaining 2017-11-02 08:35:04 +00:00
18a2500d55 Update doc markdown 2017-11-01 20:28:07 +00:00
fe07dfaabb More docs 2017-11-01 20:27:45 +00:00
97cdb4e046 Update docs 2017-11-01 20:24:11 +00:00
35c7af0b67 Remove some hard resets 2017-11-01 20:06:03 +00:00
6e9eadc2bd Fix clang 2017-11-01 20:01:46 +00:00
08550f0959 Clean up code 2017-11-01 19:54:18 +00:00
0bb694cce8 Fix GCC4.9 2017-11-01 19:46:46 +00:00
adca4b597b Fix noexcept 2017-11-01 19:03:45 +00:00
8e7ed1d83c Merge branch 'master' of github.com:TartanLlama/monadic-optional-new 2017-11-01 15:44:08 +00:00
3720227b2d Propagate triviality, conditionally delete special members 2017-11-01 15:43:58 +00:00
45b6e55233 Add version defines 2017-10-29 21:55:27 +00:00
7cfe5f71e4 Fix tests 2017-10-29 20:22:55 +00:00
4e00a30e7b Fix GCC 5.4 bug 2017-10-29 20:07:54 +00:00
9a6f22d811 Ffal constexpr fixes 2017-10-25 09:30:54 +01:00
31da15a391 Constexpr fixes 2017-10-24 16:04:31 +01:00
09249f3be0 More constexpr fixes 2017-10-24 15:59:38 +01:00
ae88cda44a More constexpr fixes 2017-10-24 15:55:40 +01:00
1b9d589024 Constexpr fixes 2017-10-24 15:46:07 +01:00
0df06afe8d Fix #2 2017-10-24 15:32:22 +01:00
98f34bed66 Fix #1 2017-10-24 15:07:29 +01:00
9fae73d55b Change namespace in README 2017-10-24 09:10:58 +01:00
29 changed files with 3126 additions and 14173 deletions

View File

@ -3,8 +3,6 @@ os:
- Visual Studio 2017
build_script:
- mkdir build
- cd build
- cmake ..
- cmake --build .
- C:\projects\optional\build\Debug\tests.exe
- cmake -Bbuild -S.
- cmake --build build
- cmake --build build --target RUN_TESTS

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
\#*
.\#*
/build/

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "cmake/tl-cmake"]
path = cmake/tl-cmake
url = https://github.com/TartanLlama/tl-cmake.git

View File

@ -1,89 +1,161 @@
language: cpp
dist: trusty
sudo: false
dist: xenial
matrix:
include:
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env: COMPILER=g++-5
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: g++-4.8 } }
env: COMPILER=g++-4.8 CXXSTD=11
- compiler: gcc
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: g++-4.9 } }
env: COMPILER=g++-4.9 CXXSTD=11
- &gcc-5
compiler: gcc
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: g++-5 } }
env: COMPILER=g++-5 CXXSTD=11
- &gcc-6
compiler: gcc
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: g++-6 } }
env: COMPILER=g++-6 CXXSTD=11
- &gcc-7
compiler: gcc
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: g++-7 } }
env: COMPILER=g++-7 CXXSTD=11
- &gcc-8
compiler: gcc
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: g++-8 } }
env: COMPILER=g++-8 CXXSTD=11
- &gcc-9
compiler: gcc
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: g++-9 } }
env: COMPILER=g++-9 CXXSTD=11
- &clang-35
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=11
- &clang-36
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=11
- &clang-37
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=11
- &clang-38
compiler: clang
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
env: COMPILER=g++-4.9
- compiler: gcc
- &xenial-clang
sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.8 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages: [clang++-3.8, libc++-dev]
env: COMPILER=clang++-3.8 CXXSTD=11
- &clang-39
compiler: clang
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
env: COMPILER=g++-4.8
- 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
- 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
- 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
- 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
- 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"
- <<: *xenial-clang
sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-3.9 main'
- ubuntu-toolchain-r-test
packages:
- clang++-3.9
- libc++-dev
env: COMPILER=clang++-3.9
packages: [clang++-3.9, libc++-dev]
env: COMPILER=clang++-3.9 CXXSTD=11
- &clang-4
compiler: clang
addons:
apt:
sources:
- <<: *xenial-clang
sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-4.0 main'
- ubuntu-toolchain-r-test
packages: [clang++-4.0, libc++-dev]
env: COMPILER=clang++-4.0 CXXSTD=11
- &clang-5
compiler: clang
addons:
apt:
sources:
- <<: *xenial-clang
sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main'
- ubuntu-toolchain-r-test
packages: [clang++-5.0, libc++-dev]
env: COMPILER=clang++-5.0 CXXSTD=11
- &clang-6
compiler: clang
addons:
apt:
sources: [llvm-toolchain-xenial-6.0, ubuntu-toolchain-r-test]
packages: [clang++-6.0, libc++-dev]
env: COMPILER=clang++-6.0 CXXSTD=11
- &clang-7
compiler: clang
addons:
apt:
sources: [llvm-toolchain-xenial-7, ubuntu-toolchain-r-test]
packages: [clang++-7, libc++-7-dev, libc++abi-7-dev]
env: COMPILER=clang++-7 CXXSTD=11
- &clang-8
compiler: clang
addons:
apt:
sources: [llvm-toolchain-xenial-8, ubuntu-toolchain-r-test]
packages: [clang++-8, libc++-8-dev, libc++abi-8-dev]
env: COMPILER=clang++-8 CXXSTD=11
- &clang-9
compiler: clang
addons:
apt:
sources:
- <<: *xenial-clang
sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
- ubuntu-toolchain-r-test
packages: [clang++-9, libc++-9-dev, libc++abi-9-dev]
env: COMPILER=clang++-9 CXXSTD=11
- { <<: *gcc-5, env: COMPILER=g++-5 CXXSTD=14 }
- { <<: *gcc-6, env: COMPILER=g++-6 CXXSTD=14 }
- { <<: *gcc-7, env: COMPILER=g++-7 CXXSTD=14 }
- { <<: *gcc-8, env: COMPILER=g++-8 CXXSTD=14 }
- { <<: *gcc-9, env: COMPILER=g++-9 CXXSTD=14 }
- { <<: *gcc-7, env: COMPILER=g++-7 CXXSTD=17 }
- { <<: *gcc-8, env: COMPILER=g++-8 CXXSTD=17 }
- { <<: *gcc-9, env: COMPILER=g++-9 CXXSTD=17 }
- { <<: *clang-35, env: COMPILER=clang++-3.5 CXXSTD=14 }
- { <<: *clang-36, env: COMPILER=clang++-3.6 CXXSTD=14 }
- { <<: *clang-37, env: COMPILER=clang++-3.7 CXXSTD=14 }
- { <<: *clang-38, env: COMPILER=clang++-3.8 CXXSTD=14 }
- { <<: *clang-39, env: COMPILER=clang++-3.9 CXXSTD=14 }
- { <<: *clang-4, env: COMPILER=clang++-4.0 CXXSTD=14 }
- { <<: *clang-5, env: COMPILER=clang++-5.0 CXXSTD=14 }
- { <<: *clang-6, env: COMPILER=clang++-6.0 CXXSTD=14 }
- { <<: *clang-7, env: COMPILER=clang++-7 CXXSTD=14 }
- { <<: *clang-8, env: COMPILER=clang++-8 CXXSTD=14 }
- { <<: *clang-9, env: COMPILER=clang++-9 CXXSTD=14 }
- { <<: *clang-7, env: COMPILER=clang++-7 CXXSTD=17 }
- { <<: *clang-8, env: COMPILER=clang++-8 CXXSTD=17 }
- { <<: *clang-9, env: COMPILER=clang++-9 CXXSTD=17 }
before_install:
- sudo apt update
- sudo apt install -y apt-transport-https ca-certificates gnupg software-properties-common
- curl -L https://apt.kitware.com/keys/kitware-archive-latest.asc | sudo apt-key add -
- sudo apt-add-repository 'deb https://apt.kitware.com/ubuntu/ xenial main'
- sudo apt update
install:
- if [ "$CXX" = "clang++" ]; then export CXX="$COMPILER -stdlib=libc++"; fi
- if [ "$CXX" = "g++" ]; then export CXX="$COMPILER"; fi
- sudo apt install -y cmake
script: mkdir build && cd build && cmake .. && make && ./tests
script:
- /usr/bin/cmake -B build -S . "-DCMAKE_CXX_STANDARD=$CXXSTD" "-DCMAKE_CXX_COMPILER=$COMPILER"
- /usr/bin/cmake --build build
- /usr/bin/cmake --build build --target test

View File

@ -1,41 +1,145 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.14)
project(tl-optional
HOMEPAGE_URL https://tl.tartanllama.xyz
DESCRIPTION "C++11/14/17 std::optional with functional-style extensions and reference support"
VERSION 1.0.0
LANGUAGES CXX)
project(optional)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(GNUInstallDirs)
include(FetchContent)
include(CTest)
# Prepare "Catch" library for other executables
set(CATCH_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/test)
add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
find_program(DPKG_BUILDPACKAGE_FOUND dpkg-buildpackage)
find_program(RPMBUILD_FOUND rpmbuild)
# Make test executable
set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests/noexcept.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests/make_optional.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests/in_place.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests/relops.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests/observers.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tests/extensions.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/nullopt.cpp)
if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
add_executable(tests ${TEST_SOURCES})
option(OPTIONAL_BUILD_PACKAGE "Build packages" ON)
cmake_dependent_option(OPTIONAL_BUILD_TESTS
"Enable tl::optional tests" ON
"BUILD_TESTING" OFF)
cmake_dependent_option(OPTIONAL_BUILD_PACKAGE_DEB
"Create DEB Package (${PROJECT_NAME})" ON
"OPTIONAL_BUILD_PACKAGE;DPKG_BUILDPACKAGE_FOUND" OFF)
cmake_dependent_option(OPTIONAL_BUILD_PACKAGE_RPM
"Create RPM Package (${PROJECT_NAME})" ON
"OPTIONAL_BUILD_PACKAGE;RPMBUILD_FOUND" OFF)
cmake_dependent_option(OPTIONAL_BUILD_PACKAGE_MSI
"Create MSI (${PROJECT_NAME})" ON
"OPTIONAL_BUILD_PACKAGE;CMAKE_HOST_WIN32" OFF)
add_library(optional INTERFACE)
target_sources(optional INTERFACE ${CMAKE_SOURCE_DIR}/optional.hpp)
target_include_directories(optional INTERFACE ${CMAKE_SOURCE_DIR})
target_include_directories(optional
INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_link_libraries(tests Catch optional)
set_property(TARGET tests PROPERTY CXX_STANDARD 14)
if (NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
add_library(tl::optional ALIAS optional)
endif()
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}")
find_package(standardese) # find standardese after installation
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
COMPATIBILITY SameMajorVersion
ARCH_INDEPENDENT)
# generates a custom target that will run standardese to generate the documentation
if (standardese_FOUND)
standardese_generate(optional
INCLUDE_DIRECTORY .
CONFIG ${CMAKE_SOURCE_DIR}/standardese.config
INPUT optional.hpp)
endif ()
install(TARGETS optional EXPORT ${PROJECT_NAME}-targets)
install(EXPORT ${PROJECT_NAME}-targets
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}"
NAMESPACE tl::
FILE "${PROJECT_NAME}-targets.cmake")
install(FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake"
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}")
install(DIRECTORY "include/" TYPE INCLUDE)
if (OPTIONAL_BUILD_TESTS)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(CATCH_INSTALL_HELPERS OFF)
set(CATCH_BUILD_TESTING OFF)
set(CATCH_INSTALL_DOCS OFF)
FetchContent_Declare(Catch2 URL
https://github.com/catchorg/Catch2/archive/v2.9.2.zip)
FetchContent_MakeAvailable(Catch2)
file(GENERATE OUTPUT catch.main.cpp
CONTENT [[
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
]])
set_property(SOURCE ${PROJECT_BINARY_DIR}/catch.main.cpp
PROPERTY
GENERATED ON)
add_library(${PROJECT_NAME}-catch-main OBJECT)
target_sources(${PROJECT_NAME}-catch-main PRIVATE
${PROJECT_BINARY_DIR}/catch.main.cpp)
target_compile_options(${PROJECT_NAME}-catch-main
PUBLIC
$<$<AND:$<CXX_COMPILER_ID:Clang>,$<BOOL:"$ENV{TRAVIS}">>:-stdlib=libc++>
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra>)
target_link_options(${PROJECT_NAME}-catch-main
PUBLIC
$<$<AND:$<CXX_COMPILER_ID:Clang>,$<BOOL:"$ENV{TRAVIS}">>:-stdlib=libc++>)
target_link_libraries(${PROJECT_NAME}-catch-main
PUBLIC
Catch2::Catch2
optional)
file(GLOB test-sources CONFIGURE_DEPENDS tests/*.cpp)
foreach (source IN LISTS test-sources)
get_filename_component(name "${source}" NAME_WE)
set(test "${PROJECT_NAME}-test-${name}")
add_executable(${test}
"${source}"
$<TARGET_OBJECTS:${PROJECT_NAME}-catch-main>)
target_link_libraries(${test}
PRIVATE
${PROJECT_NAME}-catch-main)
add_test(NAME ${PROJECT_NAME}::test::${name} COMMAND ${test})
endforeach()
endif()
if (NOT OPTIONAL_BUILD_PACKAGE)
return()
endif()
list(APPEND source-generators TBZ2 TGZ TXZ ZIP)
if (OPTIONAL_BUILD_PACKAGE_MSI)
list(APPEND binary-generators "WIX")
endif()
if (OPTIONAL_BUILD_PACKAGE_DEB)
list(APPEND binary-generators "DEB")
endif()
if (OPTIONAL_BUILD_PACKAGE_RPM)
list(APPEND binary-generators "RPM")
endif()
set(CPACK_SOURCE_GENERATOR ${source-generators})
set(CPACK_GENERATOR ${binary-generators})
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILENAME}")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Sy Brand")
list(APPEND CPACK_SOURCE_IGNORE_FILES /.git/ /build/ .gitignore .DS_Store)
include(CPack)

View File

@ -1,6 +1,8 @@
# 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.
[![Documentation Status](https://readthedocs.org/projects/tl-docs/badge/?version=latest)](https://tl.tartanllama.xyz/en/latest/?badge=latest)
Clang + GCC: [![Linux Build Status](https://travis-ci.org/TartanLlama/optional.png?branch=master)](https://travis-ci.org/TartanLlama/optional)
MSVC: [![Windows Build Status](https://ci.appveyor.com/api/projects/status/k5x00xa11y3s5wsg?svg=true)](https://ci.appveyor.com/project/TartanLlama/optional)
@ -8,7 +10,7 @@ MSVC: [![Windows Build Status](https://ci.appveyor.com/api/projects/status/k5x00
For example, instead of writing this code:
```
```c++
std::optional<image> get_cute_cat (const image& img) {
auto cropped = crop_to_cat(img);
if (!cropped) {
@ -31,8 +33,8 @@ std::optional<image> get_cute_cat (const image& img) {
You can do this:
```
std::optional<image> get_cute_cat (const image& img) {
```c++
tl::optional<image> get_cute_cat (const image& img) {
return crop_to_cat(img)
.and_then(add_bow_tie)
.and_then(make_eyes_sparkle)
@ -41,8 +43,6 @@ std::optional<image> get_cute_cat (const image& img) {
}
```
Full documentation available at [optional.tartanllama.xyz](https://optional.tartanllama.xyz)
The interface is the same as `std::optional`, but the following member functions are also defined. Explicit types are for clarity.
- `map`: carries out some operation on the stored object if there is one.
@ -56,35 +56,59 @@ The interface is the same as `std::optional`, but the following member functions
* `tl::optional<std::size_t> s = opt_string.map_or(&std::string::size, 0);`
- `map_or_else`: carries out a `map` if there is a value, otherwise returns the result of a given default function.
* `std::size_t get_default();`
* `tl::optional<std::size_t> s = opt_string.map_or(&std::string::size, get_default);`
* `tl::optional<std::size_t> s = opt_string.map_or_else(&std::string::size, get_default);`
- `conjunction`: returns the argument if a value is stored in the optional, otherwise an empty optional.
* `tl::make_optional(42).conjunction(13); //13`
* `tl::optional<int>){}.conjunction(13); //empty`
* `tl::optional<int>{}.conjunction(13); //empty`
- `disjunction`: returns the argument if the optional is empty, otherwise the current value.
* `tl::make_optional(42).disjunction(13); //42`
* `tl::optional<int>{}.disjunction(13); //13`
- `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:
```c++
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:
```c++
int j = 8;
o = j;
&*o == &j; //true
```
### Compiler support
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++ 5.5
* g++ 4.9
* g++ 4.8
- Windows CI
- Windows
* MSVC 2015
* MSVC 2017
- Linux manual
* g++ 7.2
* g++ 5.4
### Dependencies

View File

@ -0,0 +1,3 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/tl-optional-targets.cmake")

View File

@ -1 +0,0 @@
optional.tartanllama.xyz

View File

@ -1,673 +0,0 @@
# Header file `optional.hpp`<a id="optional.hpp"></a>
<pre><code class="language-cpp">namespace <a href='doc_optional.md#optional.hpp'>tl</a>
{
class <a href='doc_optional.md#tl::monostate'>monostate</a>;
struct <a href='doc_optional.md#tl::in_place_t'>in_place_t</a>;
constexpr <a href='doc_optional.md#tl::in_place_t'>in_place_t{}</a> <a href='doc_optional.md#tl::in_place'>in_place</a>;
struct <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>;
static constexpr nullopt_t nullopt;
class <a href='doc_optional.md#optional.hpp'>bad_optional_access</a>;
template &lt;class T&gt;
class <a href='doc_optional.md#tl::optional-T-'>optional</a>;
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constoptional-U-&)'>operator==</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constoptional-U-&)'>operator!=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constoptional-U-&)'>operator&lt;</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constoptional-U-&)'>operator&gt;</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constoptional-U-&)'>operator&lt;=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constoptional-U-&)'>operator&gt;=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator==</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator==</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator!=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator!=</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&lt;</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&lt;</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&lt;=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&lt;=</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&gt;</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&gt;</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&gt;=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
template &lt;class T&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,tl::nullopt_t)'>operator&gt;=</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator==</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator==</a>(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator!=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator!=</a>(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&lt;</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&lt;</a>(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&lt;=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&lt;=</a>(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&gt;</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&gt;</a>(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&gt;=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
template &lt;class T, class U&gt;
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator&gt;=</a>(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
template &lt;class T&gt;
void swap(optional&lt;T&gt; &amp;lhs, optional&lt;T&gt; &amp;rhs);
template &lt;class T&gt;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional&lt;detail::decay_t&lt;T&gt;&gt;</a> <a href='doc_optional.md#optional.hpp'>make_optional</a>(T&amp;&amp; v);
template &lt;class T, class ... Args&gt;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a> <a href='doc_optional.md#optional.hpp'>make_optional</a>(Args&amp;&amp;... args);
template &lt;class T, class U, class ... Args&gt;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a> <a href='doc_optional.md#optional.hpp'>make_optional</a>(<a href='http://en.cppreference.com/mwiki/index.php?title=Special%3ASearch&search=std::initializer_list%3cU%3e'>std::initializer_list&lt;U&gt;</a> il, Args&amp;&amp;... args);
}
namespace <a href='doc_optional.md#optional.hpp'>std</a>
{
}</code></pre>
## Class `tl::monostate`<a id="tl::monostate"></a>
<pre><code class="language-cpp">class monostate
{
};</code></pre>
Used to represent an optional with no data; essentially a bool
## Struct `tl::in_place_t`<a id="tl::in_place_t"></a>
<pre><code class="language-cpp">struct in_place_t
{
<a href='doc_optional.md#tl::in_place_t'>in_place_t</a>() = default;
};</code></pre>
A tag type to tell optional to construct its value in-place
## Variable `tl::in_place`<a id="tl::in_place"></a>
<pre><code class="language-cpp">constexpr <a href='doc_optional.md#tl::in_place_t'>in_place_t{}</a> in_place;</code></pre>
A tag to tell optional to construct its value in-place
## Struct `tl::nullopt_t`<a id="tl::nullopt_t"></a>
<pre><code class="language-cpp">struct nullopt_t
{
struct <a href='doc_optional.md#tl::nullopt_t'>do_not_use</a>;
constexpr <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>(<a href='doc_optional.md#tl::nullopt_t'>do_not_use</a>, <a href='doc_optional.md#tl::nullopt_t'>do_not_use</a>) noexcept;
};</code></pre>
A tag type to represent an empty optional
## Variable `tl::nullopt`<a id="tl::nullopt"></a>
<pre><code class="language-cpp">static constexpr nullopt_t nullopt;</code></pre>
Represents an empty optional
*Examples*:
tl::optional<int> a = tl::nullopt;
void foo (tl::optional<int>);
foo(tl::nullopt); //pass an empty optional
## Class template `tl::optional`<a id="tl::optional-T-"></a>
<pre><code class="language-cpp">template &lt;class T&gt;
class optional
{
public:
template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) &amp;;
template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) &amp;&amp;;
template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) const &amp;;
template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) const &amp;&amp;;
template &lt;class F&gt; auto map(F &amp;&amp;f) &amp;;
template &lt;class F&gt; auto map(F &amp;&amp;f) &amp;&amp;;
template &lt;class F&gt; auto map(F &amp;&amp;f) const &amp;;
template &lt;class F&gt; auto map(F &amp;&amp;f) const &amp;&amp;;
template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) &amp;;
template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) &amp;&amp;;
template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) const &amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) &amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) &amp;&amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) const &amp;;
template &lt;class F, class U&gt;
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&amp;&amp; f, U&amp;&amp; u) const &amp;&amp;;
template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) &amp;;
template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) &amp;&amp;;
template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) const &amp;;
template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) const &amp;&amp;;
template &lt;class U&gt;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional&lt;typename std::decay&lt;U&gt;::type&gt;</a> <a href='doc_optional.md#tl::optional-T-::conjunction(U&&)const'>conjunction</a>(U&amp;&amp; u) const;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;&amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;&amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;&amp;;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::disjunction(constoptional-T-&)&'>disjunction</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;&amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() &amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() const &amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() &amp;&amp;;
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() const &amp;&amp;;
using <a href='doc_optional.md#tl::optional-T-'>value_type</a> = T;
constexpr <a href='doc_optional.md#tl::optional-T-::optional()'>optional</a>() noexcept = default;
constexpr <a href='doc_optional.md#tl::optional-T-::optional()'>optional</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
constexpr <a href='doc_optional.md#tl::optional-T-::optional(constoptional-T-&)'>optional</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs);
constexpr <a href='doc_optional.md#tl::optional-T-::optional(optional-T-&&)'>optional</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) noexcept(std::is_nothrow_move_constructible&lt;T&gt;::value);
template &lt;class... Args&gt; constexpr explicit optional(in_place_t, Args&amp;&amp;... args);
template &lt;class U, class... Args&gt;
constexpr explicit optional(in_place_t, std::initializer_list&lt;U&gt;&amp;, Args&amp;&amp;... args);
template &lt;class U=T&gt; constexpr optional(U &amp;&amp;u);
template &lt;class U&gt; optional(const optional&lt;U&gt; &amp;rhs);
template &lt;class U&gt; optional(optional&lt;U&gt; &amp;&amp;rhs);
<a href='doc_optional.md#tl::optional-T-::~optional()'>~optional</a>() = default;
<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; <a href='doc_optional.md#tl::optional-T-::operator=(tl::nullopt_t)'>operator=</a>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; <a href='doc_optional.md#tl::optional-T-::operator=(constoptional-T-&)'>operator=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs);
<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; <a href='doc_optional.md#tl::optional-T-::operator=(optional-T-&&)'>operator=</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) noexcept(std::is_nothrow_move_assignable&lt;T&gt;::value&amp;&amp;std::is_nothrow_move_constructible&lt;T&gt;::value);
optional &amp;operator=(U &amp;&amp;u);
optional &amp;operator=(const optional&lt;U&gt; &amp; rhs);
optional &amp;operator=(optional&lt;U&gt; &amp;&amp; rhs);
template &lt;class ... Args&gt;
T&amp; <a href='doc_optional.md#tl::optional-T-::emplace(Args&&...)'>emplace</a>(Args&amp;&amp;... args);
template &lt;class U, class... Args&gt;
T&amp; emplace(std::initializer_list&lt;U&gt; il, Args &amp;&amp;... args);
void <a href='doc_optional.md#tl::optional-T-::swap(optional-T-&)'>swap</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) noexcept(std::is_nothrow_move_constructible&lt;T&gt;::value&amp;&amp;detail::is_nothrow_swappable&lt;T&gt;::value);
constexpr const T *operator-&gt;() const;
constexpr T *operator-&gt;();
constexpr T &amp;operator*();
constexpr const T &amp;operator*() const;
constexpr bool <a href='doc_optional.md#tl::optional-T-::has_value()const'>has_value</a>() const noexcept;
constexpr <a href='doc_optional.md#tl::optional-T-::has_value()const'>operator bool</a>() const noexcept;
constexpr T &amp;value();
constexpr const T &amp;value() const;
template &lt;class U&gt;
constexpr T <a href='doc_optional.md#tl::optional-T-::value_or(U&&)const&'>value_or</a>(U&amp;&amp; u) const &amp;;
template &lt;class U&gt;
constexpr T <a href='doc_optional.md#tl::optional-T-::value_or(U&&)const&'>value_or</a>(U&amp;&amp; u) &amp;&amp;;
void <a href='doc_optional.md#tl::optional-T-::reset()'>reset</a>() noexcept;
};</code></pre>
An optional object is an object that contains the storage for another object and manages the lifetime of this contained object, if any. The contained object may be initialized after the optional object has been initialized, and may be destroyed before the optional object has been destroyed. The initialization state of the contained object is tracked by the optional object.
### Function template `tl::optional::and_then`<a id="tl::optional-T-::and_then(F&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) &amp;;
(2) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) &amp;&amp;;
(3) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) const &amp;;
(4) template &lt;class F&gt;
constexpr auto and_then(F &amp;&amp;f) const &amp;&amp;;</code></pre>
Carries out some operation which returns an optional on the stored object if there is one.
*Requires*: `std::invoke(std::forward<F>(f), value())` returns a `std::optional<U>` for some `U`.
*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 the return value of `std::invoke(std::forward<F>(f), value())` is returned.
### Function template `tl::optional::map`<a id="tl::optional-T-::map(F&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F&gt; auto map(F &amp;&amp;f) &amp;;
(2) template &lt;class F&gt; auto map(F &amp;&amp;f) &amp;&amp;;
(3) template &lt;class F&gt; auto map(F &amp;&amp;f) const &amp;;
(4) template &lt;class F&gt; auto map(F &amp;&amp;f) const &amp;&amp;;</code></pre>
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.
### Function template `tl::optional::or_else`<a id="tl::optional-T-::or_else(F&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) &amp;;
(2) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) &amp;&amp;;
(3) template &lt;class F&gt; optional&lt;T&gt; or_else (F &amp;&amp;f) const &amp;;</code></pre>
Calls `f` if the optional is empty
*Requires*: `std::invoke_result_t<F>` must be void or convertible to `optional<T>`.
*Effects*: If `*this` has a value, returns `*this`. Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`.
### Function template `tl::optional::map_or`<a id="tl::optional-T-::map_or(F&&,U&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) &amp;;
(2) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) &amp;&amp;;
(3) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) const &amp;;
(4) template &lt;class F, class U&gt;
U map_or(F&amp;&amp; f, U&amp;&amp; u) const &amp;&amp;;</code></pre>
Maps the stored value with `f` if there is one, otherwise returns `u`
If there is a value stored, then `f` is called with `**this` and the value is returned. Otherwise `u` is returned.
### Function template `tl::optional::map_or_else`<a id="tl::optional-T-::map_or_else(F&&,U&&)&"></a>
<pre><code class="language-cpp">(1) template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) &amp;;
(2) template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) &amp;&amp;;
(3) template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) const &amp;;
(4) template &lt;class F, class U&gt;
auto map_or_else(F &amp;&amp;f, U &amp;&amp;u) const &amp;&amp;;</code></pre>
Maps the stored value with `f` if there is one, otherwise calls `u` and returns the result.
If there is a value stored, then `f` is called with `**this` and the value is returned. Otherwise `std::forward<U>(u)()` is returned.
### Function template `tl::optional::conjunction`<a id="tl::optional-T-::conjunction(U&&)const"></a>
<pre><code class="language-cpp">template &lt;class U&gt;
constexpr <a href='doc_optional.md#tl::optional-T-'>optional&lt;typename std::decay&lt;U&gt;::type&gt;</a> conjunction(U&amp;&amp; u) const;</code></pre>
*Returns*: `u` if `*this` has a value, otherwise an empty optional.
### Function `tl::optional::disjunction`<a id="tl::optional-T-::disjunction(constoptional-T-&)&"></a>
<pre><code class="language-cpp">(1) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;;
(2) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;;
(3) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) &amp;&amp;;
(4) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) const &amp;&amp;;
(5) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;;
(6) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;;
(7) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) &amp;&amp;;
(8) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) const &amp;&amp;;</code></pre>
*Returns*: `rhs` if `*this` is empty, otherwise the current value.
### Function `tl::optional::take`<a id="tl::optional-T-::take()&"></a>
<pre><code class="language-cpp">(1) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() &amp;;
(2) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() const &amp;;
(3) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() &amp;&amp;;
(4) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() const &amp;&amp;;</code></pre>
Takes the value out of the optional, leaving it empty
### Default constructor `tl::optional::optional`<a id="tl::optional-T-::optional()"></a>
<pre><code class="language-cpp">(1) constexpr optional() noexcept = default;
(2) constexpr optional(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;</code></pre>
Constructs an optional that does not contain a value.
### Constructor `tl::optional::optional`<a id="tl::optional-T-::optional(constoptional-T-&)"></a>
<pre><code class="language-cpp">constexpr optional(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs);</code></pre>
Copy constructor
If `rhs` contains a value, the stored value is direct-initialized with it. Otherwise, the constructed optional is empty.
### Constructor `tl::optional::optional`<a id="tl::optional-T-::optional(optional-T-&&)"></a>
<pre><code class="language-cpp">constexpr optional(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) noexcept(std::is_nothrow_move_constructible&lt;T&gt;::value);</code></pre>
Move constructor
If `rhs` contains a value, the stored value is direct-initialized with it. Otherwise, the constructed optional is empty.
### Function template `tl::optional::optional`<a id="tl::optional-T-::optional(detail::enable_if_t-std::is_constructible-T,Args...-::value,in_place_t-,Args&&...)"></a>
<pre><code class="language-cpp">(1) template &lt;class... Args&gt; constexpr explicit optional(in_place_t, Args&amp;&amp;... args);
(2) template &lt;class U, class... Args&gt;
constexpr explicit optional(in_place_t, std::initializer_list&lt;U&gt;&amp;, Args&amp;&amp;... args);</code></pre>
Constructs the stored value in-place using the given arguments.
### Function template `tl::optional::optional`<a id="tl::optional-T-::optional(U&&)"></a>
<pre><code class="language-cpp">template &lt;class U=T&gt; constexpr optional(U &amp;&amp;u);</code></pre>
Constructs the stored value with `u`.
### Function template `tl::optional::optional`<a id="tl::optional-T-::optional(constoptional-U-&)"></a>
<pre><code class="language-cpp">template &lt;class U&gt; optional(const optional&lt;U&gt; &amp;rhs);</code></pre>
Converting copy constructor.
### Function template `tl::optional::optional`<a id="tl::optional-T-::optional(optional-U-&&)"></a>
<pre><code class="language-cpp">template &lt;class U&gt; optional(optional&lt;U&gt; &amp;&amp;rhs);</code></pre>
Converting move constructor.
### Destructor `tl::optional::~optional`<a id="tl::optional-T-::~optional()"></a>
<pre><code class="language-cpp">~optional() = default;</code></pre>
Destroys the stored value if there is one.
### Assignment operator `tl::optional::operator=`<a id="tl::optional-T-::operator=(tl::nullopt_t)"></a>
<pre><code class="language-cpp"><a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; operator=(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;</code></pre>
Assignment to empty.
Destroys the current value if there is one.
### Assignment operator `tl::optional::operator=`<a id="tl::optional-T-::operator=(constoptional-T-&)"></a>
<pre><code class="language-cpp"><a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; operator=(const <a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs);</code></pre>
Copy assignment.
Copies the value from `rhs` if there is one. Otherwise resets the stored value in `*this`.
### Assignment operator `tl::optional::operator=`<a id="tl::optional-T-::operator=(optional-T-&&)"></a>
<pre><code class="language-cpp"><a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; operator=(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp;&amp; rhs) noexcept(std::is_nothrow_move_assignable&lt;T&gt;::value&amp;&amp;std::is_nothrow_move_constructible&lt;T&gt;::value);</code></pre>
Move assignment.
Moves the value from `rhs` if there is one. Otherwise resets the stored value in `*this`.
### Assignment operator `tl::optional::operator=`<a id="tl::optional-T-::operator=(U&&)"></a>
<pre><code class="language-cpp">optional &amp;operator=(U &amp;&amp;u);</code></pre>
Assigns the stored value from `u`, destroying the old value if there was one.
### Assignment operator `tl::optional::operator=`<a id="tl::optional-T-::operator=(constoptional-U-&)"></a>
<pre><code class="language-cpp">optional &amp;operator=(const optional&lt;U&gt; &amp; rhs);</code></pre>
Converting copy assignment operator.
Copies the value from `rhs` if there is one. Otherwise resets the stored value in `*this`.
### Assignment operator `tl::optional::operator=`<a id="tl::optional-T-::operator=(optional-U-&&)"></a>
<pre><code class="language-cpp">optional &amp;operator=(optional&lt;U&gt; &amp;&amp; rhs);</code></pre>
Converting move assignment operator.
Moves the value from `rhs` if there is one. Otherwise resets the stored value in `*this`.
### Function template `tl::optional::emplace`<a id="tl::optional-T-::emplace(Args&&...)"></a>
<pre><code class="language-cpp">(1) template &lt;class ... Args&gt;
T&amp; emplace(Args&amp;&amp;... args);
(2) template &lt;class U, class... Args&gt;
T&amp; emplace(std::initializer_list&lt;U&gt; il, Args &amp;&amp;... args);</code></pre>
Constructs the value in-place, destroying the current one if there is one.
### Function `tl::optional::swap`<a id="tl::optional-T-::swap(optional-T-&)"></a>
<pre><code class="language-cpp">void swap(<a href='doc_optional.md#tl::optional-T-'>optional</a>&amp; rhs) noexcept(std::is_nothrow_move_constructible&lt;T&gt;::value&amp;&amp;detail::is_nothrow_swappable&lt;T&gt;::value);</code></pre>
Swaps this optional with the other.
If neither optionals have a value, nothing happens. If both have a value, the values are swapped. If one has a value, it is moved to the other and the movee is left valueless.
### Operator `tl::optional::operator->`<a id="tl::optional-T-::operator--()const"></a>
<pre><code class="language-cpp">(1) constexpr const T *operator-&gt;() const;
(2) constexpr T *operator-&gt;();</code></pre>
*Returns*: a pointer to the stored value
*Requires*: a value is stored
### Operator `tl::optional::operator*`<a id="tl::optional-T-::operator*()&"></a>
<pre><code class="language-cpp">(1) constexpr T &amp;operator*();
(2) constexpr const T &amp;operator*() const;</code></pre>
*Returns*: the stored value
*Requires*: a value is stored
### Function `tl::optional::has_value`<a id="tl::optional-T-::has_value()const"></a>
<pre><code class="language-cpp">(1) constexpr bool has_value() const noexcept;
(2) constexpr operator bool() const noexcept;</code></pre>
*Returns*: whether or not the optional has a value
### Function `tl::optional::value`<a id="tl::optional-T-::value()&"></a>
<pre><code class="language-cpp">(1) constexpr T &amp;value();
(2) constexpr const T &amp;value() const;</code></pre>
*Returns*: the contained value if there is one, otherwise throws \[bad\_optional\_access\]
### Function template `tl::optional::value_or`<a id="tl::optional-T-::value_or(U&&)const&"></a>
<pre><code class="language-cpp">(1) template &lt;class U&gt;
constexpr T value_or(U&amp;&amp; u) const &amp;;
(2) template &lt;class U&gt;
constexpr T value_or(U&amp;&amp; u) &amp;&amp;;</code></pre>
*Returns*: the stored value if there is one, otherwise returns `u`
### Function `tl::optional::reset`<a id="tl::optional-T-::reset()"></a>
<pre><code class="language-cpp">void reset() noexcept;</code></pre>
Destroys the stored value if one exists, making the optional empty
-----
## Comparison operator `tl::operator==`<a id="tl::operator==(constoptional-T-&,constoptional-U-&)"></a>
<pre><code class="language-cpp">(1) template &lt;class T, class U&gt;
constexpr bool operator==(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
(2) template &lt;class T, class U&gt;
constexpr bool operator!=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
(3) template &lt;class T, class U&gt;
constexpr bool operator&lt;(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
(4) template &lt;class T, class U&gt;
constexpr bool operator&gt;(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
(5) template &lt;class T, class U&gt;
constexpr bool operator&lt;=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);
(6) template &lt;class T, class U&gt;
constexpr bool operator&gt;=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;U&gt;</a>&amp; rhs);</code></pre>
Compares two optional objects
If both optionals contain a value, they are compared with `T`s relational operators. Otherwise `lhs` and `rhs` are equal only if they are both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs` is not.
## Comparison operator `tl::operator==`<a id="tl::operator==(constoptional-T-&,tl::nullopt_t)"></a>
<pre><code class="language-cpp">(1) template &lt;class T&gt;
constexpr bool operator==(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
(2) template &lt;class T&gt;
constexpr bool operator==(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;
(3) template &lt;class T&gt;
constexpr bool operator!=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
(4) template &lt;class T&gt;
constexpr bool operator!=(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;
(5) template &lt;class T&gt;
constexpr bool operator&lt;(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
(6) template &lt;class T&gt;
constexpr bool operator&lt;(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;
(7) template &lt;class T&gt;
constexpr bool operator&lt;=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
(8) template &lt;class T&gt;
constexpr bool operator&lt;=(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;) noexcept;
(9) template &lt;class T&gt;
constexpr bool operator&gt;(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
(10) template &lt;class T&gt;
constexpr bool operator&gt;(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;) noexcept;
(11) template &lt;class T&gt;
constexpr bool operator&gt;=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp;, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
(12) template &lt;class T&gt;
constexpr bool operator&gt;=(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs) noexcept;</code></pre>
Compares an optional to a `nullopt`
Equivalent to comparing the optional to an empty optional
## Comparison operator `tl::operator==`<a id="tl::operator==(constoptional-T-&,constU&)"></a>
<pre><code class="language-cpp">(1) template &lt;class T, class U&gt;
constexpr bool operator==(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
(2) template &lt;class T, class U&gt;
constexpr bool operator==(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
(3) template &lt;class T, class U&gt;
constexpr bool operator!=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
(4) template &lt;class T, class U&gt;
constexpr bool operator!=(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
(5) template &lt;class T, class U&gt;
constexpr bool operator&lt;(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
(6) template &lt;class T, class U&gt;
constexpr bool operator&lt;(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
(7) template &lt;class T, class U&gt;
constexpr bool operator&lt;=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
(8) template &lt;class T, class U&gt;
constexpr bool operator&lt;=(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
(9) template &lt;class T, class U&gt;
constexpr bool operator&gt;(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
(10) template &lt;class T, class U&gt;
constexpr bool operator&gt;(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);
(11) template &lt;class T, class U&gt;
constexpr bool operator&gt;=(const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; lhs, const U&amp; rhs);
(12) template &lt;class T, class U&gt;
constexpr bool operator&gt;=(const U&amp; lhs, const <a href='doc_optional.md#tl::optional-T-'>optional&lt;T&gt;</a>&amp; rhs);</code></pre>
Compares the optional with a value.
If the optional has a value, it is compared with the other value using `T`s relational operators. Otherwise, the optional is considered less than the value.
-----

2062
include/tl/optional.hpp Normal file

File diff suppressed because it is too large Load Diff

13
library.json Normal file
View File

@ -0,0 +1,13 @@
{
"name": "optional",
"version": "1.0.0",
"build": {
"includeDir": "include",
"srcFilter": [
"+<*>",
"-<.git>",
"-<cmake/>",
"-<tests/*>"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/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
View File

@ -0,0 +1,107 @@
#include <catch2/catch.hpp>
#include <tl/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&) { return *this; }
T& operator=(T&&) { return *this; };
~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

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,8 @@
#include "catch.hpp"
#include "optional.hpp"
#define TOKENPASTE(x, y) x##y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define STATIC_REQUIRE(e) \
constexpr bool TOKENPASTE2(rqure, __LINE__) = e; \
REQUIRE(e);
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
TEST_CASE("Constexpr", "[constexpr]") {
#if !defined(TL_OPTIONAL_MSVC2015) && !defined(TL_OPTIONAL_GCC49)
#if !defined(TL_OPTIONAL_MSVC2015) && defined(TL_OPTIONAL_CXX14)
SECTION("empty construct") {
constexpr tl::optional<int> o2{};
constexpr tl::optional<int> o3 = {};

View File

@ -1,31 +1,62 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
#include <vector>
struct foo {
foo() = default;
foo(foo&) = delete;
foo(foo&&) {};
};
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);
}
std::vector<foo> v;
v.emplace_back();
tl::optional<std::vector<foo>> ov = std::move(v);
REQUIRE(ov->size() == 1);
}

13
tests/emplace.cpp Normal file
View File

@ -0,0 +1,13 @@
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
#include <utility>
#include <tuple>
TEST_CASE("Emplace", "[emplace]") {
tl::optional<std::pair<std::pair<int,int>, std::pair<double, double>>> i;
i.emplace(std::piecewise_construct, std::make_tuple(0,2), std::make_tuple(3,4));
REQUIRE(i->first.first == 0);
REQUIRE(i->first.second == 2);
REQUIRE(i->second.first == 3);
REQUIRE(i->second.second == 4);
}

View File

@ -1,353 +1,415 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
#include <string>
#define TOKENPASTE(x, y) x##y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define STATIC_REQUIRE(e) \
constexpr bool TOKENPASTE2(rqure, __LINE__) = e; \
REQUIRE(e);
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 &) { 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") {
#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);
const tl::optional<int> o21 = 42;
auto o21r = std::move(o21).map([](int) { return; });
REQUIRE(o21r);
constexpr tl::optional<int> o11 = 42;
constexpr auto o11r = std::move(o11).and_then(get_opt_int);
REQUIRE(*o11r == 42);
tl::optional<int> o24 = tl::nullopt;
auto o24r = o24.map([](int) { return 42; });
REQUIRE(!o24r);
constexpr tl::optional<int> o18 = tl::nullopt;
constexpr auto o18r = o18.and_then(get_opt_int);
REQUIRE(!o18r);
tl::optional<int> o25 = tl::nullopt;
auto o25r = o25.map([](int) { return; });
REQUIRE(!o25r);
constexpr tl::optional<int> o19 = tl::nullopt;
constexpr auto o19r = std::move(o19).and_then(get_opt_int);
REQUIRE(!o19r);
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);
int i = 42;
tl::optional<int&> o39 = i;
o39.map([](int& x){x = 12;});
REQUIRE(i == 12);
}
SECTION("map constexpr") {
#if !defined(_MSC_VER) && defined(TL_OPTIONAL_CXX14)
// 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> o20 = 42;
constexpr auto o20r = std::move(o20).map(get_int);
STATIC_REQUIRE(*o20r == 42);
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("transform") { // lhs is empty
tl::optional<int> o1;
auto o1r = o1.transform([](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.transform([](int i) { return i + 2; });
STATIC_REQUIRE((std::is_same<decltype(o2r), tl::optional<int>>::value));
REQUIRE(o2r.value() == 42);
struct rval_call_transform {
double operator()(int) && { return 42.0; };
};
// ensure that function object is forwarded
tl::optional<int> o3 = 42;
auto o3r = o3.transform(rval_call_transform{});
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).transform([](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.transform([](const int& i) { return i + 2; });
STATIC_REQUIRE((std::is_same<decltype(o5r), tl::optional<int>>::value));
REQUIRE(o5r.value() == 42);
// test void return
tl::optional<int> o7 = 40;
auto f7 = [](const int&) { return; };
auto o7r = o7.transform(f7);
STATIC_REQUIRE(
(std::is_same<decltype(o7r), tl::optional<tl::monostate>>::value));
REQUIRE(o7r.has_value());
// test each overload in turn
tl::optional<int> o8 = 42;
auto o8r = o8.transform([](int) { return 42; });
REQUIRE(*o8r == 42);
tl::optional<int> o9 = 42;
auto o9r = o9.transform([](int) { return; });
REQUIRE(o9r);
tl::optional<int> o12 = 42;
auto o12r = std::move(o12).transform([](int) { return 42; });
REQUIRE(*o12r == 42);
tl::optional<int> o13 = 42;
auto o13r = std::move(o13).transform([](int) { return; });
REQUIRE(o13r);
const tl::optional<int> o16 = 42;
auto o16r = o16.transform([](int) { return 42; });
REQUIRE(*o16r == 42);
const tl::optional<int> o17 = 42;
auto o17r = o17.transform([](int) { return; });
REQUIRE(o17r);
const tl::optional<int> o20 = 42;
auto o20r = std::move(o20).transform([](int) { return 42; });
REQUIRE(*o20r == 42);
const tl::optional<int> o21 = 42;
auto o21r = std::move(o21).transform([](int) { return; });
REQUIRE(o21r);
tl::optional<int> o24 = tl::nullopt;
auto o24r = o24.transform([](int) { return 42; });
REQUIRE(!o24r);
tl::optional<int> o25 = tl::nullopt;
auto o25r = o25.transform([](int) { return; });
REQUIRE(!o25r);
tl::optional<int> o28 = tl::nullopt;
auto o28r = std::move(o28).transform([](int) { return 42; });
REQUIRE(!o28r);
tl::optional<int> o29 = tl::nullopt;
auto o29r = std::move(o29).transform([](int) { return; });
REQUIRE(!o29r);
const tl::optional<int> o32 = tl::nullopt;
auto o32r = o32.transform([](int) { return 42; });
REQUIRE(!o32r);
const tl::optional<int> o33 = tl::nullopt;
auto o33r = o33.transform([](int) { return; });
REQUIRE(!o33r);
const tl::optional<int> o36 = tl::nullopt;
auto o36r = std::move(o36).transform([](int) { return 42; });
REQUIRE(!o36r);
const tl::optional<int> o37 = tl::nullopt;
auto o37r = std::move(o37).transform([](int) { return; });
REQUIRE(!o37r);
// callable which returns a reference
tl::optional<int> o38 = 42;
auto o38r = o38.transform([](int& i) -> const int& { return i; });
REQUIRE(o38r);
REQUIRE(*o38r == 42);
int i = 42;
tl::optional<int&> o39 = i;
o39.transform([](int& x) {x = 12; });
REQUIRE(i == 12);
}
SECTION("transform constexpr") {
#if !defined(_MSC_VER) && defined(TL_OPTIONAL_CXX14)
// test each overload in turn
constexpr tl::optional<int> o16 = 42;
constexpr auto o16r = o16.transform(get_int);
STATIC_REQUIRE(*o16r == 42);
constexpr tl::optional<int> o20 = 42;
constexpr auto o20r = std::move(o20).transform(get_int);
STATIC_REQUIRE(*o20r == 42);
constexpr tl::optional<int> o32 = tl::nullopt;
constexpr auto o32r = o32.transform(get_int);
STATIC_REQUIRE(!o32r);
constexpr tl::optional<int> o36 = tl::nullopt;
constexpr auto o36r = std::move(o36).transform(get_int);
STATIC_REQUIRE(!o36r);
#endif
}
SECTION("and_then") {
// lhs is empty
tl::optional<int> o1;
auto o1r = o1.and_then([](int) { 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) { 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) { 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) { 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) { return tl::make_optional(42); });
REQUIRE(*o8r == 42);
tl::optional<int> o9 = 42;
auto o9r =
std::move(o9).and_then([](int) { return tl::make_optional(42); });
REQUIRE(*o9r == 42);
const tl::optional<int> o10 = 42;
auto o10r = o10.and_then([](int) { return tl::make_optional(42); });
REQUIRE(*o10r == 42);
const tl::optional<int> o11 = 42;
auto o11r =
std::move(o11).and_then([](int) { return tl::make_optional(42); });
REQUIRE(*o11r == 42);
tl::optional<int> o16 = tl::nullopt;
auto o16r = o16.and_then([](int) { return tl::make_optional(42); });
REQUIRE(!o16r);
tl::optional<int> o17 = tl::nullopt;
auto o17r =
std::move(o17).and_then([](int) { return tl::make_optional(42); });
REQUIRE(!o17r);
const tl::optional<int> o18 = tl::nullopt;
auto o18r = o18.and_then([](int) { return tl::make_optional(42); });
REQUIRE(!o18r);
const tl::optional<int> o19 = tl::nullopt;
auto o19r = std::move(o19).and_then([](int) { return tl::make_optional(42); });
REQUIRE(!o19r);
int i = 3;
tl::optional<int&> o20{i};
std::move(o20).and_then([](int& r){return tl::optional<int&>{++r};});
REQUIRE(o20);
REQUIRE(i == 4);
}
SECTION("constexpr and_then") {
#if !defined(_MSC_VER) && defined(TL_OPTIONAL_CXX14)
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 +420,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 +458,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) && !defined(TL_OPTIONAL_GCC55)
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{});
}
};

View File

@ -1,4 +1,4 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
TEST_CASE("Hashing", "[hash]") {}

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
#include <tuple>
#include <vector>

45
tests/issues.cpp Normal file
View File

@ -0,0 +1,45 @@
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
#include <type_traits>
struct foo{
int& v() { return i; }
int i = 0;
};
int& x(int& i) { i = 42; return i;}
TEST_CASE("issue 14") {
tl::optional<foo> f = foo{};
auto v = f.map(&foo::v).map(x);
static_assert(std::is_same<decltype(v), tl::optional<int&>>::value, "Must return a reference");
REQUIRE(f->i == 42);
REQUIRE(*v == 42);
REQUIRE((&f->i) == (&*v));
}
struct fail_on_copy_self {
int value;
fail_on_copy_self(int v) : value(v) {}
fail_on_copy_self(const fail_on_copy_self& other) : value(other.value) {
REQUIRE(&other != this);
}
};
TEST_CASE("issue 15") {
tl::optional<fail_on_copy_self> o = fail_on_copy_self(42);
o = o;
REQUIRE(o->value == 42);
}
TEST_CASE("issue 33") {
int i = 0;
int j = 0;
tl::optional<int&> a = i;
a.emplace(j);
*a = 42;
REQUIRE(j == 42);
REQUIRE(*a == 42);
REQUIRE(a.has_value());
}

View File

@ -1,2 +0,0 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
#include <tuple>
#include <vector>
@ -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);
}

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
TEST_CASE("Noexcept", "[noexcept]") {
tl::optional<int> o1{4};
@ -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
}
@ -80,7 +80,7 @@ TEST_CASE("Noexcept", "[noexcept]") {
struct throw_move_assign {
throw_move_assign() = default;
throw_move_assign(throw_move_assign &&){};
throw_move_assign &operator=(const throw_move_assign &) {}
throw_move_assign &operator=(const throw_move_assign &) { return *this; }
};
using nothrow_opt = tl::optional<nothrow_move_assign>;

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
TEST_CASE("Nullopt", "[nullopt]") {
tl::optional<int> o1 = tl::nullopt;

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
struct move_detector {
move_detector() = default;

View File

@ -1,5 +1,5 @@
#include "catch.hpp"
#include "optional.hpp"
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
TEST_CASE("Relational ops", "[relops]") {
tl::optional<int> o1{4};

26
tests/swap.cpp Normal file
View File

@ -0,0 +1,26 @@
#include <catch2/catch.hpp>
#include <tl/optional.hpp>
TEST_CASE("Swap value", "[swap.value]") {
tl::optional<int> o1 = 42;
tl::optional<int> o2 = 12;
o1.swap(o2);
CHECK(o1.value() == 12);
CHECK(o2.value() == 42);
}
TEST_CASE("Swap value with null intialized", "[swap.value_nullopt]") {
tl::optional<int> o1 = 42;
tl::optional<int> o2 = tl::nullopt;
o1.swap(o2);
CHECK(!o1.has_value());
CHECK(o2.value() == 42);
}
TEST_CASE("Swap null intialized with value", "[swap.nullopt_value]") {
tl::optional<int> o1 = tl::nullopt;
tl::optional<int> o2 = 42;
o1.swap(o2);
CHECK(o1.value() == 42);
CHECK(!o2.has_value());
}