Last Updated: December 21, 2020
·
30.04K
· rahul8590

Using getopt vs Boost in C++ to handle arguments

Hey guys, this is my small tutorial, rather experience of mine while deciding on which argument handler to use. Usually in C++ it gets cumbersome to use the vanilla version of arg counts and argv. So,I prefer using standard libraries for the same. Makes your life a bit easier.

Lets start with boost. Whenever, I see a boost library I get very tempted to use it, since many of my programs use it especially asynchronous ones. But for something as reasonably simple and succinct as option parser do I need boost ? Taking a look at their libraries , this is what gets included.

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/positional_options.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/errors.hpp>
#include <boost/program_options/option.hpp>
#include <boost/program_options/value_semantic.hpp>
#include <boost/program_options/version.hpp>

Now thats a lot of libraries which makes me wonder , Do I really need them ?

The following is what the actual boost program looks like

#include<iostream>
#include<boost/program_options.hpp>

using namespace std;

int main(int argc, char **argv)
{

    namespace po = boost::program_options;
    po::options_description desc("Allowed options");
    desc.add_options()
    ("help", "describe arguments")
    ("flag", po::value<int>(), "flag");

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);    

    if (vm.count("help")) {
    cout << desc << "\n";
    return 1;
    }

    if (vm.count("flag")) {
    cout << "flag is set to " 
    << vm["flag"].as<int>() << ".\n";
    } else {
    cout << "flag not set.\n";
    }
}

The above program is rip-off from the example mentioned in the boost website. The kind of dependencies and libraries involved makes me feel like hell. No, offence to boost fans. Boost indeed is a great library, but common , do we need soo many header files and namespaces just for an option parser ? I dont think so!

Now this is where getopt bestows its simplicity.

#include<iostream>
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>


using namespace std;
int main(int argc, char **argv)
{
    int opt,a,b,c;
    while ((opt = getopt(argc,argv,"abc:d")) != EOF)
        switch(opt)
        {
            case 'a': a = 1; cout <<" a is enabled"<<a <<endl; break;
            case 'b': b = 1; cout <<" b is enabled"<<b <<endl; break;
            case 'c': c = 1; cout << "value of c is"<< optarg <<endl ; break;
            case '?': fprintf(stderr, "usuage is \n -a : for enabling a \n -b : for enabling b \n -c: <value> ");
            default: cout<<endl; abort();
        }

    return 0;
}

Definitely this seems a lot more simple. But getopt has its own set of caveats. Firstly, when you call getopt the following variables are set.

  1. optarg variable is meant for those arguments which have some parameters to be passed. Like the option c in the above program. one can easily mess-up , if you happen to use that in your program. (yes there are ways to avoid it)
  2. The options passed to getopt function doesn't seem very nice. abc:d tells c is a option where some parameter is expected.
  3. You need to have your own logic to multiplex various arguments. For example, If I want the user not to have -c 5 -f 6 to be passed together or not have options -a -b set at the same time. It needs to be handled by my code and not the option parser. Many of you might be arguing on option parser is not meant to do that, but it will be nice to have that as a feature.

Lastly, both the methods of parsing arguments are have their pros and cons. But there isnt a solution which entails best of the both. Its time I start coding my own library :)

1 Response
Add your response

getOpt is not there on Windows unless one install the Microsoft SFU. So I think Boost is a better option.

over 1 year ago ·