Command Line Flags in C++

A Minimalist's Guide

You are programming a tool in C++. Not a huge tool, not a tool where you care enough about performance to say, use faster data structures than those provided by the standard library, but one where you feel compelled to add some useful options. After a brief and uninspiring survery of the field you settle on the old standard for implementing program settings, you’re going to parse argv.

Parsing command line options falls into the nightmare zone of complexity. It is not so trivial that there’s a single obvious approach, nor is it difficult enough to be solely the domain of white papers published by subject matter experts. Rather it’s an approachable problem that everyone likes to take a swing at it, and following that swing run to write a blog post about their clever little solution; completely flooding search results with endless mediocre code.

With that in mind, here is my clever little solution.

A Little Cleverness

The requirements for my argv handler were thus:

Since I want a POD struct at the end of this, that’s as good a place to start as any:

Some interesting notes about Figure 1:

My preferred way to switch on strings is to use a map to std::function:

In Figure 2 we have an unordered map that when passed a string will produce a lambda (or other std::function thingy) which can perform the applicable modification to MySettings. If this seems extremely obvious and simple to you, that’s because it is.

As a point of style, it may be appropriate to use a macro here to minimize repetition and make the code more declarative:

Of course, there are legitimate schools of thought which teach that the C preprocessor is of the devil. My immortal soul is worth little and less to me personally, so I like the macro.

For the single argument parameters we simply iterate on this approach. Our lambdas will now take two arguments, the first being the MySettings struct and the second being the string argument:

It should be clear from this point that this approach can be further iterated to support flags with arbitrary numbers of arguments and parsing complexity. All that’s left to do is put the pieces together and actually parse argv.

Putting the Pieces Together

We’re going to need a function that does four things in the following order:

  1. Check if a string from argv is a NoArg option, and if so invoke the appropriate handler
  2. Check if the string is a OneArg option, and if so collect the string argument (throwing if no such argument exists), then invoke the appropriate handler
  3. Check if infile has been set, and if not set it with the string
  4. Warn if infile has already been set and the flag is unrecognized

Let’s do it:

Final Thoughts

Parsing argv is not a hard problem and I make no pretence that the solution presented here is innovative or ground breaking. Yet if the internet is to be believed handling these humble flags requires at least one operating system specific framework or a single header file copied from Dr. Dobbs circa 2003.

Dependencies are not necessarily bad things, but C++ is not Javascript. There’s no need to pull in outside frameworks to solve a problem we can hack in a few dozens lines of code ourselves.

See also: Addendum: Handling Positional Arguments