c++boostc++17boost-program-optionsc-str

Boost.Program_Options: Why does options_description_easy_init::operator() not have an overload for std::string?


Consider this MCVE:

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

namespace po = boost::program_options;
using namespace std;

po::options_description createOptions(const std::string& description, const map<string, string>& opts) {
    po::options_description newoptions(description);

    for (const auto& [k, v] : opts) {
        newoptions.add_options()(k, v);
    }
    return newoptions;
}

int main() {

    map<string, string> descMap = {
        { "key", "description" },
        { "hello", "world" }
    };

    auto opts = createOptions("My options", descMap);

    cout << opts << endl;
}

I am trying to write a convenience function to reduce the amount of C&P code when inserting similar options into an options_description object (the original code uses notifiers which were removed for simplicity, but add even more boilerplate). To my surprise, there is no options_description_easy_init::operator() overload that accepts std::string, thus the example fails to compile.

While I could easily make the example work by calling .c_str() on k and v within the for loop, of course this would be dangerous. Is there any reason why the boost devs left out such an important overload? Why didn't they use const std::string& as argument in the first place?

And how can I make this code work without .c_str()? There is no indication that the pointer memory will be copied internally (which would be odd anyway) and I really don't feel like going back in time and managing memory on my own :-)


Solution

  • Looking into the implementation, it seems that internally the const char* argument passed to options_description_easy_init::operator() is wrapped by a new option_description object, which eventually converts the argument into a std::string. So as commented by @pptaszni, it is safe to call .c_str() on the std::string arguments to pass them to the program options.

    What I still don't understand, however, is why there is not an std::string overload. I consider this a design flaw (also considering that options_description has a constructor taking std::string).