1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-04-29 12:13:52 +00:00

Removing enum conversion

This commit is contained in:
Henry Fredrick Schreiner 2018-04-06 20:39:42 +02:00 committed by Henry Schreiner
parent ef2d497fcb
commit 5d9a5636bc
6 changed files with 25 additions and 30 deletions

View File

@ -9,6 +9,7 @@ Note: This is the final release with `requires`, please switch to `needs`.
* Support for `std::optional`, `std::experimental::optional`, and `boost::optional` added if `__has_include` is supported [#95]
* All macros/CMake variables now start with `CLI11_` instead of just `CLI_` [#95]
* The internal stream was not being cleared before use in some cases. Fixed. [#95]
* Using an emum now requires explicit conversion overload [#97]
Other, non-user facing changes:
@ -24,6 +25,7 @@ Other, non-user facing changes:
[#90]: https://github.com/CLIUtils/CLI11/issues/90
[#92]: https://github.com/CLIUtils/CLI11/issues/92
[#95]: https://github.com/CLIUtils/CLI11/pull/95
[#97]: https://github.com/CLIUtils/CLI11/pull/97
## Version 1.4: More feedback

View File

@ -307,7 +307,11 @@ Also, in a related note, the `App` you get a pointer to is stored in the parent
## How it works
Every `add_` option you have seen so far depends on one method that takes a lambda function. Each of these methods is just making a different lambda function with capture to populate the option. The function has full access to the vector of strings, so it knows how many times an option was passed or how many arguments it received (flags add empty strings to keep the counts correct). The lambda returns `true` if it could validate the option strings, and
`false` if it failed. If you wanted to extend this to support a new type, just use a lambda. An example of a new parser for `complex<double>` that supports all of the features of a standard `add_options` call is in [one of the tests](./tests/NewParseTest.cpp). A simpler example is shown below:
`false` if it failed.
Other values can be added as long as they support `operator>>` (and defaults can be printed if they support `operator<<`). To add an enum, for example, provide a custom `operator>>` with an `istream` (inside the CLI namespace is fine if you don't want to interfere with an existing `operator>>`).
If you wanted to extend this to support a completely new type, just use a lambda. An example of a new parser for `complex<double>` that supports all of the features of a standard `add_options` call is in [one of the tests](./tests/NewParseTest.cpp). A simpler example is shown below:
### Example

View File

@ -4,7 +4,7 @@
# gives output on failed tests without having to set an environment variable.
#
#
set(gtest_force_shared_crt CACHE INTERNAL ON)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(BUILD_SHARED_LIBS OFF)
if(CMAKE_VERSION VERSION_LESS 3.11)

View File

@ -1,12 +1,22 @@
#include <sstream>
#include <CLI/CLI.hpp>
enum Level : std::int32_t { High, Medium, Low };
enum class Level : int { High, Medium, Low };
std::istream &operator>>(std::istream &in, Level &level) {
int i;
in >> i;
level = static_cast<Level>(i);
return in;
}
std::ostream &operator<<(std::ostream &in, const Level &level) { return in << static_cast<int>(level); }
int main(int argc, char **argv) {
CLI::App app;
Level level;
app.add_set("-l,--level", level, {High, Medium, Low}, "Level settings")
app.add_set("-l,--level", level, {Level::High, Level::Medium, Level::Low}, "Level settings")
->set_type_name("enum/Level in {High=0, Medium=1, Low=2}");
CLI11_PARSE(app, argc, argv);

View File

@ -74,8 +74,7 @@ constexpr const char *type_name() {
/// Signed integers / enums
template <typename T,
enable_if_t<(std::is_integral<T>::value && std::is_signed<T>::value) || std::is_enum<T>::value,
detail::enabler> = detail::dummy>
enable_if_t<(std::is_integral<T>::value && std::is_signed<T>::value), detail::enabler> = detail::dummy>
bool lexical_cast(std::string input, T &output) {
try {
size_t n = 0;
@ -124,7 +123,7 @@ bool lexical_cast(std::string input, T &output) {
/// String and similar
template <typename T,
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !std::is_enum<T>::value &&
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
std::is_assignable<T &, std::string>::value,
detail::enabler> = detail::dummy>
bool lexical_cast(std::string input, T &output) {
@ -134,7 +133,7 @@ bool lexical_cast(std::string input, T &output) {
/// Non-string parsable
template <typename T,
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !std::is_enum<T>::value &&
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value &&
!std::is_assignable<T &, std::string>::value,
detail::enabler> = detail::dummy>
bool lexical_cast(std::string input, T &output) {

View File

@ -321,8 +321,8 @@ TEST_F(TApp, ComplexOptMulti) {
run();
EXPECT_FLOAT_EQ(val.real(), 1);
EXPECT_FLOAT_EQ(val.imag(), 2);
EXPECT_DOUBLE_EQ(val.real(), 1);
EXPECT_DOUBLE_EQ(val.imag(), 2);
}
TEST_F(TApp, MissingValueNonRequiredOpt) {
@ -643,26 +643,6 @@ TEST_F(TApp, NotRequiedExpectedDoubleShort) {
EXPECT_THROW(run(), CLI::ArgumentMismatch);
}
TEST_F(TApp, EnumTest) {
enum Level : std::int32_t { High, Medium, Low };
Level level = Level::Low;
app.add_option("--level", level);
args = {"--level", "1"};
run();
EXPECT_EQ(level, Level::Medium);
}
TEST_F(TApp, NewEnumTest) {
enum class Level2 : std::int32_t { High, Medium, Low };
Level2 level = Level2::Low;
app.add_option("--level", level);
args = {"--level", "1"};
run();
EXPECT_EQ(level, Level2::Medium);
}
TEST_F(TApp, RequiredFlags) {
app.add_flag("-a")->required();
app.add_flag("-b")->mandatory(); // Alternate term