From 3a9c02aa7404e20a0c1126616ac86a61cc7f2d00 Mon Sep 17 00:00:00 2001 From: "Taylor C. Richberger" Date: Sat, 7 May 2016 12:05:44 -0600 Subject: fix ADL. Add unified initializer list --- args.hxx | 50 ++++++++++++++++++++++++++++++++++++++++---------- test.cxx | 35 +++++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/args.hxx b/args.hxx index 7be47af..f079f29 100644 --- a/args.hxx +++ b/args.hxx @@ -151,6 +151,42 @@ namespace args } }; + struct EitherOpt + { + bool isShort; + char shortOpt; + std::string longOpt; + EitherOpt(const std::string &opt) : isShort(false), longOpt(opt) {} + EitherOpt(const char *opt) : isShort(false), longOpt(opt) {} + EitherOpt(const char opt) : isShort(true), shortOpt(opt) {} + }; + + std::unordered_set GetLong(std::initializer_list opts) + { + std::unordered_set longOpts; + for (const EitherOpt &opt: opts) + { + if (!opt.isShort) + { + longOpts.insert(opt.longOpt); + } + } + return longOpts; + } + + std::unordered_set GetShort(std::initializer_list opts) + { + std::unordered_set shortOpts; + for (const EitherOpt &opt: opts) + { + if (opt.isShort) + { + shortOpts.insert(opt.shortOpt); + } + } + return shortOpts; + } + /** A class of "matchers", specifying short and long options that can possibly be matched * * This is supposed to be constructed and then passed in, not used directly from user code. @@ -179,20 +215,14 @@ namespace args /** Specify short and long opts as initializer lists */ - Matcher(const std::initializer_list &shortIn, const std::initializer_list &longIn) : + Matcher(std::initializer_list shortIn, std::initializer_list longIn) : shortOpts(std::begin(shortIn), std::end(shortIn)), longOpts(std::begin(longIn), std::end(longIn)) {} - /** Specify short opts only as initializer lists - */ - Matcher(const std::initializer_list &shortIn) : - shortOpts(std::begin(shortIn), std::end(shortIn)) - {} - - /** Specify long opts only as initializer lists + /** Specify a mixed single initializer-list of both short and long opts */ - Matcher(const std::initializer_list &longIn) : - longOpts(std::begin(longIn), std::end(longIn)) + Matcher(std::initializer_list in) : + shortOpts(GetShort(in)), longOpts(GetLong(in)) {} Matcher(Matcher &&other) : shortOpts(std::move(other.shortOpts)), longOpts(std::move(other.longOpts)) diff --git a/test.cxx b/test.cxx index 3ad5533..84cd6ce 100644 --- a/test.cxx +++ b/test.cxx @@ -4,6 +4,14 @@ #include +std::istream& operator>>(std::istream& is, std::tuple& ints) +{ + is >> std::get<0>(ints); + is.get(); + is >> std::get<1>(ints); + return is; +} + #include #define CATCH_CONFIG_MAIN @@ -59,6 +67,25 @@ TEST_CASE("Argument flags work as expected, with clustering", "[args]") REQUIRE_FALSE(bix); } +TEST_CASE("Unified argument lists for match work", "[args]") +{ + args::ArgumentParser parser("This is a test program.", "This goes after the options."); + args::ArgFlag foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"}); + args::Flag bar(parser, "BAR", "test flag", args::Matcher{"bar", 'b'}); + args::ArgFlag baz(parser, "BAZ", "test flag", args::Matcher{'a', "baz"}); + args::ArgFlag bim(parser, "BAZ", "test flag", args::Matcher{'B', "bim"}); + args::Flag bix(parser, "BAZ", "test flag", args::Matcher{"bix"}); + parser.ParseArgs(std::vector{"-bftest", "--baz=7.555e2", "--bim", "c"}); + REQUIRE(foo); + REQUIRE(foo.value == "test"); + REQUIRE(bar); + REQUIRE(baz); + REQUIRE((baz.value > 755.49 && baz.value < 755.51)); + REQUIRE(bim); + REQUIRE(bim.value == 'c'); + REQUIRE_FALSE(bix); +} + TEST_CASE("Invalid argument parsing throws parsing exceptions", "[args]") { args::ArgumentParser parser("This is a test program.", "This goes after the options."); @@ -173,14 +200,6 @@ TEST_CASE("Argument groups should nest", "[args]") #include -std::istream& operator>>(std::istream& is, std::tuple& ints) -{ - is >> std::get<0>(ints); - is.get(); - is >> std::get<1>(ints); - return is; -} - void DoublesReader(const std::string &name, const std::string &value, std::tuple &destination) { size_t commapos = 0; -- cgit v1.2.1