Commit 76bd60dc17ca514f2febb49382b38d526d5502a5

Authored by Jarryd Beck
1 parent e792760a

Add support for std::optional

Fixes #93. This adds C++17 only support for `std::optional` values for
command line parameters.
.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(&quot;Booleans&quot;, &quot;[boolean]&quot;) {
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
... ...