This question has come up before, but it seems that none of the answers provide alternatives with boost
-style generic programming.
Like many I use boost:program_options to parse command line line options. My current project is a program to manipulate data (e.g. images) with operators whose order is not interchangeable, e.g.
add 3 then multiply by 2
$ manipulate -in someimage.tif -a 3 -m 2
is not generally the same as
multiply by 2 then add 3
$ manipulate -in someimage.tif -m 2 -a 3
The -in
option loads the file contents into a vector current_image
, and each option on the command line modifies current_image
.
But the variable_map
container does not retain the order in which options are added. Not explicitly, at least. The answer in this post comes closest to what I have in mind, but then the amount of extra parsing code needed is about the same as with getopt()
.
Does anyone know a way to store the order of program options in the boost-provided container? Is it fundamentally impossible? Or is it possible (maybe even implemented) with a sequence container?
EDIT 1 I did find this really old post which seems still valid, stating that yes you can just iterate over a variables_map. Of course the order is not actually specified to be the same as the order on the command line (left to the compiler writers), so I guess it does still classify as a hack.
EDIT 2 That is not enough as the options are sorted by option string so the iteration order is not the same as the insertion order.
Actually what you have there is more akin to an expression grammar. I'd suggest writing a grammar/parser for that instead of (ab?)using program_options for this.
If your program takes options: use program options.
If your program takes an expression: use an expression parser.
An example:
Live On Coliru
Note
eol
as the option separator. You might want to use'\0'
instead. This was easiest because theblank
skipper already skips whitespace /except/eol
. I'm lazy :)You might wnat to mix-and-match (not treat all parameters as part of the expression). A common pattern would be
A common alternative pattern is to make the expression a single parameter:
See this approach Live on Coliru too
I was lazy again with the "Parse success" printing (I didn't want to implement
operator<<
for theOperation
type)enable debug info with
#define BOOST_SPIRIT_DEBUG
(uncomment the first line)