You accidentally returned the TStruct type from the expandBitwise . Correct it like this:
template<typename T> auto expandBitwise(T const& t) -> decltype(t.rule_) { return t.rule_; } template<typename T,typename ...Tail> auto expandBitwise(T const& t,Tail const&... tail) -> decltype(t.rule_) { return t.rule_ | expandBitwise(tail...); }
If you want to expand attributes, the inference rules of the return type become more active. Basically, what you are doing is repeating a part of the EDSL of the Spirit.
Let them exchange stories ...
Clippy: Looks like you're trying to write a command line parser. Do you want to help with this?
The DSL mechanism for your parameter parser can be implemented more systematically by creating a new proto-domain and actually creating terminals. I would have liked it somehow now.
Alternatively, you can take it completely from a different angle using Nabialek Trick.This could be the approach that I played just a few weeks ago, and I will share with you the project that I came up with: https://gist.github.com/sehe/ 2a556a8231606406fe36 # file-test-cpp
An important role is that the grammar is “fixed”:
start = -argument % '\0'; unparsed = as_string [ +~nul ] [ std::cerr << phx::val("ignoring unparsed argument: '") << _1 << "'\n" ]; argument = ('-' >> +shortopt) | ("--" >> longopt) >> -unparsed | unparsed;
Trick in:
shortopt = shortNames [_a = _1] >> lazy(_a); longopt = longNames [_a = _1] >> lazy(_a);
Where shortNames and longNames are qi::symbols parser tables built dynamically based on the variational list of CliOptions and CliFlags (I pass them as a tuple because I wanted to save the result inside the CliOption structure).
qi::lazy(_a) calls the parser that was stored in the symbol table.
As a bonus, my CliOptions analyzer has a function to generate usage information. Constructors for parsing expressions, as well as usage information, are extensible.
int main(int argc, char* argv[]) { using CliParsing::make_option; typedef std::string::const_iterator It; auto config = std::make_tuple( make_option('a', "absolutely", "absolutely"), make_option('b', "borked" , "borked") , make_option('c', "completion", "completion"), make_option('d', "debug", "turn on debugging"), make_option('e', "", "no long name") , //make_option('f', "flungeons" , "flungeons") , //make_option('g', "goofing" , "") , //make_option('m', "monitor", "monitoring level"), make_option('t', "testing" , "testing flags"), make_option('\0',"file" , "with a filename (no short name)"), make_option('y', "assume-yes", "always assume yes"), make_option('v', "verbose", "increase verbosity level"), make_option('i', "increment", "stepsize to increment with", 5) ); CliParsing::OptionGrammar<It> parser(config); using namespace phx::arg_names; const auto cmdline = std::accumulate(argv+1, argv+argc, std::string(), arg1 + arg2 + '\0'); bool ok = qi::parse(begin(cmdline), end(cmdline), parser); std::cout << "Parse success " << std::boolalpha << ok << "\n"; std::cout << parser.getUsage(); return ok? 0 : 255; }
When called with some random arguments -i 3 --completion -t --file=SOME.TXT -b huh? prints:
short form option --increment parsed ignoring unparsed argument: '3' long form switch --completion parsed short form switch --testing parsed long form switch --file parsed ignoring unparsed argument: '=SOME.TXT' short form switch --borked parsed ignoring unparsed argument: 'huh?' Parse success true --absolutely (-a) absolutely (flag) --borked (-b) borked (flag) --completion (-c) completion (flag) --debug (-d) turn on debugging (flag) -e no long name (flag) --testing (-t) testing flags (flag) --file with a filename (no short name) (flag) --assume-yes (-y) always assume yes (flag) --verbose (-v) increase verbosity level (flag) --increment (-i) stepsize to increment with (option with value; default '5')
As you can see, not all parameters have been implemented yet (in particular, -- to mark the end of the list of options).