forked from TartanLlama/optional
Compare commits
146 Commits
v0.1
...
platformio
Author | SHA1 | Date | |
---|---|---|---|
5c42d8fa3b | |||
0dfc7b4e41 | |||
8177b93e7f | |||
352b529889 | |||
e165e3554c | |||
c325c63b17 | |||
dcebd5897f | |||
54f7f970bf | |||
2673f3f9b3 | |||
83a0b49e5e | |||
ce266d5280 | |||
b074bee409 | |||
084a9001f4 | |||
5c4876059c | |||
71a8031dd2 | |||
a2650823a0 | |||
aef62df93e | |||
359499d904 | |||
9839b761e0 | |||
d613d3422d | |||
3cfcb3ff2d | |||
d7356bb01c | |||
8fbb0262a1 | |||
6ce85550f3 | |||
53697d4a36 | |||
c3752db7e8 | |||
4b22ab1ba6 | |||
06032ebdae | |||
2d42ed8304 | |||
b8f4ca1169 | |||
0aa68c8d47 | |||
fada9fae5f | |||
8be5c63925 | |||
7de669d9c7 | |||
f632a98e84 | |||
9399c30330 | |||
d2c6fa68c7 | |||
dff20e9c9f | |||
7ef0154330 | |||
4304148904 | |||
1de2f2a49c | |||
5d3d6c399a | |||
1baad184f0 | |||
c194f73a07 | |||
47b120fd53 | |||
99b2a15863 | |||
dc02563d7b | |||
3449fbc904 | |||
b53059c63d | |||
25f8f28a9a | |||
6c5e6d6477 | |||
4d5453bc56 | |||
068d3db664 | |||
fd6c65e7f9 | |||
aecb8fe6db | |||
0d449821ca | |||
6738107bae | |||
8b1c3fb67f | |||
dd8ab0232e | |||
dc129ecf10 | |||
bf0efe1625 | |||
9df8d1be39 | |||
35e4c6e889 | |||
aa74eb709f | |||
5dd9ed7e2c | |||
48d70a1604 | |||
c8a6658f9f | |||
04b817f0d3 | |||
6e8235c085 | |||
b3b2715a95 | |||
90b00674dd | |||
e0a542f960 | |||
b72cc392b6 | |||
9f01853678 | |||
d9d1a54abc | |||
0dd57d441c | |||
9a1b033113 | |||
d67e7c2eac | |||
e8b28f2e34 | |||
5143f9577a | |||
f82f78b5b6 | |||
3a20e3f8cd | |||
779cf10329 | |||
effc941116 | |||
94b7563fdf | |||
d8973a6524 | |||
ac8134265c | |||
10e687e188 | |||
74a422b824 | |||
dccbc0b23e | |||
27b2163d10 | |||
3452cc1c8c | |||
2ab4f77498 | |||
cb52a3b744 | |||
d7ec1da407 | |||
4bde006cb5 | |||
14cfd77197 | |||
57d659daf5 | |||
883df6b427 | |||
f621ca663e | |||
8b408f5fd6 | |||
632bc4e1ad | |||
717027db9b | |||
8c3f042b12 | |||
c4e3b3ee14 | |||
bdaa41ce8c | |||
e589ae4321 | |||
6c73b8113f | |||
32656c4556 | |||
b3dc6d1a52 | |||
247677394f | |||
5a3f094ec7 | |||
26c00afe27 | |||
4308924a38 | |||
6c4178a947 | |||
c67aaff948 | |||
b9486ce776 | |||
a1d27b2aba | |||
d9ce8cf5c5 | |||
e62348c128 | |||
39030e6a00 | |||
4d5f9bd785 | |||
f6802daada | |||
59cf950873 | |||
e4e32ea56d | |||
18a2500d55 | |||
fe07dfaabb | |||
97cdb4e046 | |||
35c7af0b67 | |||
6e9eadc2bd | |||
08550f0959 | |||
0bb694cce8 | |||
adca4b597b | |||
8e7ed1d83c | |||
3720227b2d | |||
45b6e55233 | |||
7cfe5f71e4 | |||
4e00a30e7b | |||
9a6f22d811 | |||
31da15a391 | |||
09249f3be0 | |||
ae88cda44a | |||
1b9d589024 | |||
0df06afe8d | |||
98f34bed66 | |||
9fae73d55b |
@ -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
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
\#*
|
||||
.\#*
|
||||
/build/
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "cmake/tl-cmake"]
|
||||
path = cmake/tl-cmake
|
||||
url = https://github.com/TartanLlama/tl-cmake.git
|
214
.travis.yml
214
.travis.yml
@ -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
|
||||
|
166
CMakeLists.txt
166
CMakeLists.txt
@ -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)
|
||||
|
52
README.md
52
README.md
@ -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.
|
||||
|
||||
[](https://tl.tartanllama.xyz/en/latest/?badge=latest)
|
||||
Clang + GCC: [](https://travis-ci.org/TartanLlama/optional)
|
||||
MSVC: [](https://ci.appveyor.com/project/TartanLlama/optional)
|
||||
|
||||
@ -8,7 +10,7 @@ MSVC: [ {
|
||||
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
|
||||
|
||||
|
3
cmake/tl-optional-config.cmake.in
Normal file
3
cmake/tl-optional-config.cmake.in
Normal file
@ -0,0 +1,3 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/tl-optional-targets.cmake")
|
@ -1 +0,0 @@
|
||||
optional.tartanllama.xyz
|
673
docs/index.md
673
docs/index.md
@ -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 <class T>
|
||||
class <a href='doc_optional.md#tl::optional-T-'>optional</a>;
|
||||
|
||||
template <class T, class U>
|
||||
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<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
template <class T, class U>
|
||||
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<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
template <class T, class U>
|
||||
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<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
template <class T, class U>
|
||||
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<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
template <class T, class U>
|
||||
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<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
template <class T, class U>
|
||||
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<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
|
||||
template <class T>
|
||||
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<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
template <class T>
|
||||
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<T></a>& rhs) noexcept;
|
||||
template <class T>
|
||||
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<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
template <class T>
|
||||
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<T></a>& rhs) noexcept;
|
||||
template <class T>
|
||||
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<T></a>&, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
template <class T>
|
||||
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<T></a>& rhs) noexcept;
|
||||
template <class T>
|
||||
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<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
template <class T>
|
||||
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<T></a>&) noexcept;
|
||||
template <class T>
|
||||
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<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
template <class T>
|
||||
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<T></a>&) noexcept;
|
||||
template <class T>
|
||||
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<T></a>&, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
template <class T>
|
||||
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<T></a>& rhs) noexcept;
|
||||
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator==</a>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator==</a>(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator!=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator!=</a>(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator<</a>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator<</a>(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator<=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator<=</a>(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator></a>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator></a>(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator>=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
template <class T, class U>
|
||||
constexpr bool <a href='doc_optional.md#tl::operator==(constoptional-T-&,constU&)'>operator>=</a>(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
|
||||
template <class T>
|
||||
void swap(optional<T> &lhs, optional<T> &rhs);
|
||||
|
||||
template <class T>
|
||||
constexpr <a href='doc_optional.md#tl::optional-T-'>optional<detail::decay_t<T>></a> <a href='doc_optional.md#optional.hpp'>make_optional</a>(T&& v);
|
||||
|
||||
template <class T, class ... Args>
|
||||
constexpr <a href='doc_optional.md#tl::optional-T-'>optional<T></a> <a href='doc_optional.md#optional.hpp'>make_optional</a>(Args&&... args);
|
||||
|
||||
template <class T, class U, class ... Args>
|
||||
constexpr <a href='doc_optional.md#tl::optional-T-'>optional<T></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<U></a> il, Args&&... 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 <class T>
|
||||
class optional
|
||||
{
|
||||
public:
|
||||
template <class F>
|
||||
constexpr auto and_then(F &&f) &;
|
||||
template <class F>
|
||||
constexpr auto and_then(F &&f) &&;
|
||||
template <class F>
|
||||
constexpr auto and_then(F &&f) const &;
|
||||
template <class F>
|
||||
constexpr auto and_then(F &&f) const &&;
|
||||
|
||||
template <class F> auto map(F &&f) &;
|
||||
template <class F> auto map(F &&f) &&;
|
||||
template <class F> auto map(F &&f) const &;
|
||||
template <class F> auto map(F &&f) const &&;
|
||||
|
||||
template <class F> optional<T> or_else (F &&f) &;
|
||||
template <class F> optional<T> or_else (F &&f) &&;
|
||||
template <class F> optional<T> or_else (F &&f) const &;
|
||||
|
||||
template <class F, class U>
|
||||
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&& f, U&& u) &;
|
||||
template <class F, class U>
|
||||
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&& f, U&& u) &&;
|
||||
template <class F, class U>
|
||||
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&& f, U&& u) const &;
|
||||
template <class F, class U>
|
||||
U <a href='doc_optional.md#tl::optional-T-::map_or(F&&,U&&)&'>map_or</a>(F&& f, U&& u) const &&;
|
||||
|
||||
template <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) &;
|
||||
template <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) &&;
|
||||
template <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) const &;
|
||||
template <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) const &&;
|
||||
|
||||
template <class U>
|
||||
constexpr <a href='doc_optional.md#tl::optional-T-'>optional<typename std::decay<U>::type></a> <a href='doc_optional.md#tl::optional-T-::conjunction(U&&)const'>conjunction</a>(U&& 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>& rhs) &;
|
||||
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>& rhs) 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>& rhs) &&;
|
||||
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>& rhs) 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>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) &;
|
||||
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>&& rhs) 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>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) &&;
|
||||
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>&& rhs) const &&;
|
||||
|
||||
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() &;
|
||||
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() const &;
|
||||
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() &&;
|
||||
<a href='doc_optional.md#tl::optional-T-'>optional</a> <a href='doc_optional.md#tl::optional-T-::take()&'>take</a>() const &&;
|
||||
|
||||
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>& 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>&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value);
|
||||
|
||||
template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);
|
||||
template <class U, class... Args>
|
||||
constexpr explicit optional(in_place_t, std::initializer_list<U>&, Args&&... args);
|
||||
|
||||
template <class U=T> constexpr optional(U &&u);
|
||||
|
||||
template <class U> optional(const optional<U> &rhs);
|
||||
|
||||
template <class U> optional(optional<U> &&rhs);
|
||||
|
||||
<a href='doc_optional.md#tl::optional-T-::~optional()'>~optional</a>() = default;
|
||||
|
||||
<a href='doc_optional.md#tl::optional-T-'>optional</a>& <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>& <a href='doc_optional.md#tl::optional-T-::operator=(constoptional-T-&)'>operator=</a>(const <a href='doc_optional.md#tl::optional-T-'>optional</a>& rhs);
|
||||
|
||||
<a href='doc_optional.md#tl::optional-T-'>optional</a>& <a href='doc_optional.md#tl::optional-T-::operator=(optional-T-&&)'>operator=</a>(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) noexcept(std::is_nothrow_move_assignable<T>::value&&std::is_nothrow_move_constructible<T>::value);
|
||||
|
||||
optional &operator=(U &&u);
|
||||
|
||||
optional &operator=(const optional<U> & rhs);
|
||||
|
||||
optional &operator=(optional<U> && rhs);
|
||||
|
||||
template <class ... Args>
|
||||
T& <a href='doc_optional.md#tl::optional-T-::emplace(Args&&...)'>emplace</a>(Args&&... args);
|
||||
template <class U, class... Args>
|
||||
T& emplace(std::initializer_list<U> il, Args &&... 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>& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&&detail::is_nothrow_swappable<T>::value);
|
||||
|
||||
constexpr const T *operator->() const;
|
||||
constexpr T *operator->();
|
||||
|
||||
constexpr T &operator*();
|
||||
constexpr const T &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 &value();
|
||||
constexpr const T &value() const;
|
||||
|
||||
template <class U>
|
||||
constexpr T <a href='doc_optional.md#tl::optional-T-::value_or(U&&)const&'>value_or</a>(U&& u) const &;
|
||||
template <class U>
|
||||
constexpr T <a href='doc_optional.md#tl::optional-T-::value_or(U&&)const&'>value_or</a>(U&& u) &&;
|
||||
|
||||
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 <class F>
|
||||
constexpr auto and_then(F &&f) &;
|
||||
|
||||
(2) template <class F>
|
||||
constexpr auto and_then(F &&f) &&;
|
||||
|
||||
(3) template <class F>
|
||||
constexpr auto and_then(F &&f) const &;
|
||||
|
||||
(4) template <class F>
|
||||
constexpr auto and_then(F &&f) const &&;</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 <class F> auto map(F &&f) &;
|
||||
|
||||
(2) template <class F> auto map(F &&f) &&;
|
||||
|
||||
(3) template <class F> auto map(F &&f) const &;
|
||||
|
||||
(4) template <class F> auto map(F &&f) const &&;</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 <class F> optional<T> or_else (F &&f) &;
|
||||
|
||||
(2) template <class F> optional<T> or_else (F &&f) &&;
|
||||
|
||||
(3) template <class F> optional<T> or_else (F &&f) const &;</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 <class F, class U>
|
||||
U map_or(F&& f, U&& u) &;
|
||||
|
||||
(2) template <class F, class U>
|
||||
U map_or(F&& f, U&& u) &&;
|
||||
|
||||
(3) template <class F, class U>
|
||||
U map_or(F&& f, U&& u) const &;
|
||||
|
||||
(4) template <class F, class U>
|
||||
U map_or(F&& f, U&& u) const &&;</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 <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) &;
|
||||
|
||||
(2) template <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) &&;
|
||||
|
||||
(3) template <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) const &;
|
||||
|
||||
(4) template <class F, class U>
|
||||
auto map_or_else(F &&f, U &&u) const &&;</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 <class U>
|
||||
constexpr <a href='doc_optional.md#tl::optional-T-'>optional<typename std::decay<U>::type></a> conjunction(U&& 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>& rhs) &;
|
||||
|
||||
(2) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>& rhs) const &;
|
||||
|
||||
(3) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>& rhs) &&;
|
||||
|
||||
(4) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(const <a href='doc_optional.md#tl::optional-T-'>optional</a>& rhs) const &&;
|
||||
|
||||
(5) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) &;
|
||||
|
||||
(6) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) const &;
|
||||
|
||||
(7) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) &&;
|
||||
|
||||
(8) constexpr <a href='doc_optional.md#tl::optional-T-'>optional</a> disjunction(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) const &&;</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() &;
|
||||
|
||||
(2) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() const &;
|
||||
|
||||
(3) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() &&;
|
||||
|
||||
(4) <a href='doc_optional.md#tl::optional-T-'>optional</a> take() const &&;</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>& 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>&& rhs) noexcept(std::is_nothrow_move_constructible<T>::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 <class... Args> constexpr explicit optional(in_place_t, Args&&... args);
|
||||
|
||||
(2) template <class U, class... Args>
|
||||
constexpr explicit optional(in_place_t, std::initializer_list<U>&, Args&&... 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 <class U=T> constexpr optional(U &&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 <class U> optional(const optional<U> &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 <class U> optional(optional<U> &&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>& 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>& operator=(const <a href='doc_optional.md#tl::optional-T-'>optional</a>& 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>& operator=(<a href='doc_optional.md#tl::optional-T-'>optional</a>&& rhs) noexcept(std::is_nothrow_move_assignable<T>::value&&std::is_nothrow_move_constructible<T>::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 &operator=(U &&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 &operator=(const optional<U> & 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 &operator=(optional<U> && 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 <class ... Args>
|
||||
T& emplace(Args&&... args);
|
||||
|
||||
(2) template <class U, class... Args>
|
||||
T& emplace(std::initializer_list<U> il, Args &&... 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>& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&&detail::is_nothrow_swappable<T>::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->() const;
|
||||
|
||||
(2) constexpr T *operator->();</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 &operator*();
|
||||
|
||||
(2) constexpr const T &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 &value();
|
||||
|
||||
(2) constexpr const T &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 <class U>
|
||||
constexpr T value_or(U&& u) const &;
|
||||
|
||||
(2) template <class U>
|
||||
constexpr T value_or(U&& u) &&;</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 <class T, class U>
|
||||
constexpr bool operator==(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
|
||||
(2) template <class T, class U>
|
||||
constexpr bool operator!=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
|
||||
(3) template <class T, class U>
|
||||
constexpr bool operator<(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
|
||||
(4) template <class T, class U>
|
||||
constexpr bool operator>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
|
||||
(5) template <class T, class U>
|
||||
constexpr bool operator<=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& rhs);
|
||||
|
||||
(6) template <class T, class U>
|
||||
constexpr bool operator>=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<U></a>& 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 <class T>
|
||||
constexpr bool operator==(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
|
||||
(2) template <class T>
|
||||
constexpr bool operator==(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs) noexcept;
|
||||
|
||||
(3) template <class T>
|
||||
constexpr bool operator!=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
|
||||
(4) template <class T>
|
||||
constexpr bool operator!=(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs) noexcept;
|
||||
|
||||
(5) template <class T>
|
||||
constexpr bool operator<(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>&, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
|
||||
(6) template <class T>
|
||||
constexpr bool operator<(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs) noexcept;
|
||||
|
||||
(7) template <class T>
|
||||
constexpr bool operator<=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
|
||||
(8) template <class T>
|
||||
constexpr bool operator<=(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>&) noexcept;
|
||||
|
||||
(9) template <class T>
|
||||
constexpr bool operator>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
|
||||
(10) template <class T>
|
||||
constexpr bool operator>(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>&) noexcept;
|
||||
|
||||
(11) template <class T>
|
||||
constexpr bool operator>=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>&, <a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>) noexcept;
|
||||
|
||||
(12) template <class T>
|
||||
constexpr bool operator>=(<a href='doc_optional.md#tl::nullopt_t'>nullopt_t</a>, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& 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 <class T, class U>
|
||||
constexpr bool operator==(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
|
||||
(2) template <class T, class U>
|
||||
constexpr bool operator==(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
|
||||
(3) template <class T, class U>
|
||||
constexpr bool operator!=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
|
||||
(4) template <class T, class U>
|
||||
constexpr bool operator!=(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
|
||||
(5) template <class T, class U>
|
||||
constexpr bool operator<(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
|
||||
(6) template <class T, class U>
|
||||
constexpr bool operator<(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
|
||||
(7) template <class T, class U>
|
||||
constexpr bool operator<=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
|
||||
(8) template <class T, class U>
|
||||
constexpr bool operator<=(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
|
||||
(9) template <class T, class U>
|
||||
constexpr bool operator>(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
|
||||
(10) template <class T, class U>
|
||||
constexpr bool operator>(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& rhs);
|
||||
|
||||
(11) template <class T, class U>
|
||||
constexpr bool operator>=(const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& lhs, const U& rhs);
|
||||
|
||||
(12) template <class T, class U>
|
||||
constexpr bool operator>=(const U& lhs, const <a href='doc_optional.md#tl::optional-T-'>optional<T></a>& 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
2062
include/tl/optional.hpp
Normal file
File diff suppressed because it is too large
Load Diff
13
library.json
Normal file
13
library.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "optional",
|
||||
"version": "1.0.0",
|
||||
"build": {
|
||||
"includeDir": "include",
|
||||
"srcFilter": [
|
||||
"+<*>",
|
||||
"-<.git>",
|
||||
"-<cmake/>",
|
||||
"-<tests/*>"
|
||||
]
|
||||
}
|
||||
}
|
1388
optional.hpp
1388
optional.hpp
File diff suppressed because it is too large
Load Diff
@ -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
107
tests/bases.cpp
Normal 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
|
11606
tests/catch.hpp
11606
tests/catch.hpp
File diff suppressed because it is too large
Load Diff
@ -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 = {};
|
||||
|
@ -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
13
tests/emplace.cpp
Normal 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);
|
||||
}
|
@ -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{});
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "catch.hpp"
|
||||
#include "optional.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/optional.hpp>
|
||||
|
||||
TEST_CASE("Hashing", "[hash]") {}
|
||||
|
@ -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
45
tests/issues.cpp
Normal 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());
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
@ -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);
|
||||
}
|
||||
|
@ -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>;
|
||||
|
@ -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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "catch.hpp"
|
||||
#include "optional.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
#include <tl/optional.hpp>
|
||||
|
||||
struct move_detector {
|
||||
move_detector() = default;
|
||||
|
@ -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
26
tests/swap.cpp
Normal 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());
|
||||
}
|
Reference in New Issue
Block a user