How does boost program_options work?
Asked Answered
M

2

9

The weird thing to me is, that boost's options_description uses multi-line code without backslash or semicolon or comma. I did a little research, but found nothing.

(Code taken from official boost's tutorial):

int opt;
po::options_description desc("Allowed options"); 
desc.add_options()
    ("help", "produce help message")
    ("optimization"   , po::value<int>(&opt)->default_value(10), "optimization level")
    ("include-path,I ", po::value< vector<string> >()          , "include path")
    ("input-file     ", po::value< vector<string> >()          , "input file") ;

How is it implemented? Is it a macro?

Mor answered 29/7, 2014 at 11:30 Comment(0)
C
21

It's a bit of a strange syntax in C++ but if you're familiar with JS (for example), you might be aware of the concept of method chaining. This is a bit like that.

add_options() returns an object with operator() defined. The second line calls operator() on the object returned by the first line. The method returns a reference to the original object, so you can keep calling operator() many times in a row.

Here's a simplified version of how it works:

#include <iostream>

class Example
{
public:
    Example & operator()(std::string arg) {
        std::cout << "added option: " << arg << "\n";
        return *this;
    }
    Example & add_options() {
        return *this;        
    }
};

int main()
{
    Example desc;
    desc.add_options()
        ("first")
        ("second")
        ("third");
    return 0;
}

As pointed out by gbjbaanb in the comments, this is actually quite similar to how chaining of assignments a = b = c = 0 works for classes. It is also similar to the behaviour that is pretty much taken for granted when using ostream::operator<<: you expect to be able to do std::cout << "string 1" << "string 2" << "string 3".

Cantata answered 29/7, 2014 at 11:38 Comment(1)
in much the same way as you can write a = b = c = 0;Incur
O
7

The add_options() method returns object that implements the "()" operator and the () operator in turn returns the same object. See the following code:

class Example
{
public:
    Example operator()(string arg)
    {
        cout << arg << endl;
        return Example();
    }
    Example func(string arg)
    {
        operator()(arg);
    }
};

int main()
{
    Example ex;
    ex.func("Line one")
           ("Line two")
           ("Line three");
    return 0;
}

This is the way it works.

Ordzhonikidze answered 29/7, 2014 at 12:8 Comment(4)
Your example is not great.Erotogenic
@Gall: I didn't claim my example is great.Ordzhonikidze
Ok, but you could do something proper like Tom Fenech ones.Erotogenic
@Gall: I agree, but this is a simple one to demonstrate the use of () operator repeatedly.Ordzhonikidze

© 2022 - 2024 — McMap. All rights reserved.