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,7 +12,8 @@ matrix: | ||
| 12 | packages: | 12 | packages: |
| 13 | - g++-4.9 | 13 | - g++-4.9 |
| 14 | sources: &sources | 14 | sources: &sources |
| 15 | - - llvm-toolchain-precise-3.8 | 15 | + - llvm-toolchain-trusty-3.8 |
| 16 | + - llvm-toolchain-trusty-5.0 | ||
| 16 | - ubuntu-toolchain-r-test | 17 | - ubuntu-toolchain-r-test |
| 17 | - os: linux | 18 | - os: linux |
| 18 | env: COMPILER=g++-4.9 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes | 19 | env: COMPILER=g++-4.9 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes |
| @@ -27,9 +28,7 @@ matrix: | @@ -27,9 +28,7 @@ matrix: | ||
| 27 | apt: | 28 | apt: |
| 28 | packages: | 29 | packages: |
| 29 | - g++-5 | 30 | - g++-5 |
| 30 | - sources: &sources | ||
| 31 | - - llvm-toolchain-precise-3.8 | ||
| 32 | - - ubuntu-toolchain-r-test | 31 | + sources: *sources |
| 33 | - os: linux | 32 | - os: linux |
| 34 | env: COMPILER=g++-5 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes | 33 | env: COMPILER=g++-5 UNICODE_OPTIONS=-DCXXOPTS_USE_UNICODE_HELP=Yes |
| 35 | addons: | 34 | addons: |
| @@ -53,9 +52,17 @@ matrix: | @@ -53,9 +52,17 @@ matrix: | ||
| 53 | - clang-3.8 | 52 | - clang-3.8 |
| 54 | - libc++-dev | 53 | - libc++-dev |
| 55 | sources: *sources | 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 | script: > | 63 | script: > |
| 57 | cmake -DCXXOPTS_BUILD_TESTS=ON -DCMAKE_CXX_COMPILER=$COMPILER | 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 | && make && make ARGS=--output-on-failure test | 66 | && make && make ARGS=--output-on-failure test |
| 60 | 67 | ||
| 61 | before_install: | 68 | before_install: |
CMakeLists.txt
| @@ -28,8 +28,14 @@ option(CXXOPTS_BUILD_EXAMPLES "Set to ON to build examples" ON) | @@ -28,8 +28,14 @@ option(CXXOPTS_BUILD_EXAMPLES "Set to ON to build examples" ON) | ||
| 28 | option(CXXOPTS_BUILD_TESTS "Set to ON to build tests" OFF) | 28 | option(CXXOPTS_BUILD_TESTS "Set to ON to build tests" OFF) |
| 29 | 29 | ||
| 30 | # request c++11 without gnu extension for the whole project and enable more warnings | 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 | set(CMAKE_CXX_EXTENSIONS OFF) | 37 | set(CMAKE_CXX_EXTENSIONS OFF) |
| 38 | + | ||
| 33 | if(MSVC) | 39 | if(MSVC) |
| 34 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W2") | 40 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W2") |
| 35 | elseif(CMAKE_CXX_COMPILER_ID MATCHES "[Cc]lang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") | 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,6 +38,11 @@ THE SOFTWARE. | ||
| 38 | #include <unordered_set> | 38 | #include <unordered_set> |
| 39 | #include <vector> | 39 | #include <vector> |
| 40 | 40 | ||
| 41 | +#ifdef __cpp_lib_optional | ||
| 42 | +#include <optional> | ||
| 43 | +#define CXXOPTS_HAS_OPTIONAL | ||
| 44 | +#endif | ||
| 45 | + | ||
| 41 | namespace cxxopts | 46 | namespace cxxopts |
| 42 | { | 47 | { |
| 43 | static constexpr struct { | 48 | static constexpr struct { |
| @@ -697,6 +702,17 @@ namespace cxxopts | @@ -697,6 +702,17 @@ namespace cxxopts | ||
| 697 | value.push_back(v); | 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 | template <typename T> | 716 | template <typename T> |
| 701 | struct type_is_container | 717 | struct type_is_container |
| 702 | { | 718 | { |
test/options.cpp
| @@ -454,3 +454,22 @@ TEST_CASE("Booleans", "[boolean]") { | @@ -454,3 +454,22 @@ TEST_CASE("Booleans", "[boolean]") { | ||
| 454 | 454 | ||
| 455 | REQUIRE(result.count("others") == 1); | 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 |