aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTaylor C. Richberger <tcr@absolute-performance.com>2016-05-07 12:05:44 -0600
committerTaylor C. Richberger <tcr@absolute-performance.com>2016-05-07 12:05:44 -0600
commit3a9c02aa7404e20a0c1126616ac86a61cc7f2d00 (patch)
treea99a7e84a3bba4300cf7c013064d4bd5d4d4c12e
parentchange README syntax (diff)
downloadargs.hxx-3a9c02aa7404e20a0c1126616ac86a61cc7f2d00.tar.xz
fix ADL. Add unified initializer list
-rw-r--r--args.hxx50
-rw-r--r--test.cxx35
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<std::string> GetLong(std::initializer_list<EitherOpt> opts)
+ {
+ std::unordered_set<std::string> longOpts;
+ for (const EitherOpt &opt: opts)
+ {
+ if (!opt.isShort)
+ {
+ longOpts.insert(opt.longOpt);
+ }
+ }
+ return longOpts;
+ }
+
+ std::unordered_set<char> GetShort(std::initializer_list<EitherOpt> opts)
+ {
+ std::unordered_set<char> 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<char> &shortIn, const std::initializer_list<std::string> &longIn) :
+ Matcher(std::initializer_list<char> shortIn, std::initializer_list<std::string> 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<char> &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<std::string> &longIn) :
- longOpts(std::begin(longIn), std::end(longIn))
+ Matcher(std::initializer_list<EitherOpt> 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 <iostream>
+std::istream& operator>>(std::istream& is, std::tuple<int, int>& ints)
+{
+ is >> std::get<0>(ints);
+ is.get();
+ is >> std::get<1>(ints);
+ return is;
+}
+
#include <args.hxx>
#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<std::string> foo(parser, "FOO", "test flag", args::Matcher{'f', "foo"});
+ args::Flag bar(parser, "BAR", "test flag", args::Matcher{"bar", 'b'});
+ args::ArgFlag<double> baz(parser, "BAZ", "test flag", args::Matcher{'a', "baz"});
+ args::ArgFlag<char> bim(parser, "BAZ", "test flag", args::Matcher{'B', "bim"});
+ args::Flag bix(parser, "BAZ", "test flag", args::Matcher{"bix"});
+ parser.ParseArgs(std::vector<std::string>{"-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 <tuple>
-std::istream& operator>>(std::istream& is, std::tuple<int, int>& 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<double, double> &destination)
{
size_t commapos = 0;