Commit 76bd60dc17ca514f2febb49382b38d526d5502a5
1 parent
e792760a
Add support for std::optional
Fixes #93. This adds C++17 only support for `std::optional` values for command line parameters.
Showing
4 changed files
with
54 additions
and
6 deletions
.travis.yml
| ... | ... | @@ -12,7 +12,8 @@ matrix: |
| 12 | 12 | packages: |
| 13 | 13 | - g++-4.9 |
| 14 | 14 | sources: &sources |
| 15 | - - llvm-toolchain-precise-3.8 | |
| 15 | + - llvm-toolchain-trusty-3.8 | |
| 16 | + - llvm-toolchain-trusty-5.0 | |
| 16 | 17 | - ubuntu-toolchain-r-test |
| 17 | 18 | - os: linux |
| 18 | 19 | env: COMPILER=g++-4.9 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes |
| ... | ... | @@ -27,9 +28,7 @@ matrix: |
| 27 | 28 | apt: |
| 28 | 29 | packages: |
| 29 | 30 | - g++-5 |
| 30 | - sources: &sources | |
| 31 | - - llvm-toolchain-precise-3.8 | |
| 32 | - - ubuntu-toolchain-r-test | |
| 31 | + sources: *sources | |
| 33 | 32 | - os: linux |
| 34 | 33 | env: COMPILER=g++-5 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes |
| 35 | 34 | addons: |
| ... | ... | @@ -53,9 +52,17 @@ matrix: |
| 53 | 52 | - clang-3.8 |
| 54 | 53 | - libc++-dev |
| 55 | 54 | sources: *sources |
| 55 | + - os: linux | |
| 56 | + env: COMPILER=clang++-5.0 CMAKE_OPTIONS=-DCXXOPTS_CXX_STANDARD=17 | |
| 57 | + addons: | |
| 58 | + apt: | |
| 59 | + packages: | |
| 60 | + - clang-5.0 | |
| 61 | + - g++-5 | |
| 62 | + sources: *sources | |
| 56 | 63 | script: > |
| 57 | 64 | cmake -DCXXOPTS_BUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER |
| 58 | - -DCMAKE_CXX_FLAGS=$CXXFLAGS $UNICODE_OPTIONS . | |
| 65 | + -DCMAKE_CXX_FLAGS=$CXXFLAGS $UNICODE_OPTIONS $CMAKE_OPTIONS . | |
| 59 | 66 | && make && make ARGS=--output-on-failure test |
| 60 | 67 | |
| 61 | 68 | before_install: | ... | ... |
CMakeLists.txt
| ... | ... | @@ -28,8 +28,14 @@ option(CXXOPTS_BUILD_EXAMPLES "Set to ON to build examples" ON) |
| 28 | 28 | option(CXXOPTS_BUILD_TESTS "Set to ON to build tests" OFF) |
| 29 | 29 | |
| 30 | 30 | # request c++11 without gnu extension for the whole project and enable more warnings |
| 31 | -set(CMAKE_CXX_STANDARD 11) | |
| 31 | +if (CXXOPTS_CXX_STANDARD) | |
| 32 | + set(CMAKE_CXX_STANDARD ${CXXOPTS_CXX_STANDARD}) | |
| 33 | +else() | |
| 34 | + set(CMAKE_CXX_STANDARD 11) | |
| 35 | +endif() | |
| 36 | + | |
| 32 | 37 | set(CMAKE_CXX_EXTENSIONS OFF) |
| 38 | + | |
| 33 | 39 | if(MSVC) |
| 34 | 40 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W2") |
| 35 | 41 | elseif(CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") | ... | ... |
include/cxxopts.hpp
| ... | ... | @@ -38,6 +38,11 @@ THE SOFTWARE. |
| 38 | 38 | #include <unordered_set> |
| 39 | 39 | #include <vector> |
| 40 | 40 | |
| 41 | +#ifdef __cpp_lib_optional | |
| 42 | +#include <optional> | |
| 43 | +#define CXXOPTS_HAS_OPTIONAL | |
| 44 | +#endif | |
| 45 | + | |
| 41 | 46 | namespace cxxopts |
| 42 | 47 | { |
| 43 | 48 | static constexpr struct { |
| ... | ... | @@ -697,6 +702,17 @@ namespace cxxopts |
| 697 | 702 | value.push_back(v); |
| 698 | 703 | } |
| 699 | 704 | |
| 705 | +#ifdef CXXOPTS_HAS_OPTIONAL | |
| 706 | + template <typename T> | |
| 707 | + void | |
| 708 | + parse_value(const std::string& text, std::optional<T>& value) | |
| 709 | + { | |
| 710 | + T result; | |
| 711 | + parse_value(text, result); | |
| 712 | + value = std::move(result); | |
| 713 | + } | |
| 714 | +#endif | |
| 715 | + | |
| 700 | 716 | template <typename T> |
| 701 | 717 | struct type_is_container |
| 702 | 718 | { | ... | ... |
test/options.cpp
| ... | ... | @@ -454,3 +454,22 @@ TEST_CASE("Booleans", "[boolean]") { |
| 454 | 454 | |
| 455 | 455 | REQUIRE(result.count("others") == 1); |
| 456 | 456 | } |
| 457 | + | |
| 458 | +#ifdef CXXOPTS_HAS_OPTIONAL | |
| 459 | +TEST_CASE("std::optional", "[optional]") { | |
| 460 | + std::optional<std::string> optional; | |
| 461 | + cxxopts::Options options("optional", " - tests optional"); | |
| 462 | + options.add_options() | |
| 463 | + ("optional", "an optional option", cxxopts::value<std::optional<std::string>>(optional)); | |
| 464 | + | |
| 465 | + Argv av({"optional", "--optional", "foo"}); | |
| 466 | + | |
| 467 | + char** argv = av.argv(); | |
| 468 | + auto argc = av.argc(); | |
| 469 | + | |
| 470 | + options.parse(argc, argv); | |
| 471 | + | |
| 472 | + REQUIRE(optional.has_value()); | |
| 473 | + CHECK(*optional == "foo"); | |
| 474 | +} | |
| 475 | +#endif | ... | ... |