I’m trying to get boost::program_options to read a ini file with multiple sections:
[slave]
address=localhost
port=1111
[slave]
address=192.168.0.1
port=2222
Is there any solution?
Thanks in advance!
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
There are a few solutions to this problem. While it may initially appear that this should be an easy task, it is often fairly involved. This is because sections are roughly equivalent to namespaces; sections are not equivalent to objects.
The above configuration has a single
slavenamespace, that contains twoaddressvalues and twoportvalues. There are not twoslaveobjects that each have anaddressandport. Due to this distinction, associating values, or pairing, must be done in the application code. This presenting the following options:Implied Pairing
With this approach, the configuration file can remain as-is. The simplicity of this approach depends on:
Without modifying the configuration, the following code:
Produces this output:
Basic Explicit Pairing
Multiple values can be occasionally be represented within a single field in a meaningful way. One common representation of both
addressandportisaddress:port. With this pairing, the resulting configuration file would like:This simplicity of this approach depends upon:
The updated code:
Produces the same output:
And the notable code modifications are as follows:
options_description‘soptionsneed to be readingslaves.slaveas astd::vector< std::string >.make_slavewill take a singlestd::stringargument, from which it will extractaddressandport.std::transformcall to only iterate over one range.Advanced Explicit Pairing
Often, multiple fields cannot be represented meaningfully as a single key-less value, or an object has optional fields. For these cases, an additional level of syntax and parsing needs to occur. While applications can introduce their own syntax and parsers, I suggest leveraging Boost.ProgramOption’s command line syntax (
--key valueand--key=value) and parsers. The resulting configuration file could look like:The updated code:
Produces the same output as the previous approaches:
And the notable code modifications are as follows:
copy_ifsince it was an overlooked algorithm in C++03.option_builderunary functor to help provide idiomatic reuse for applying transformations.make_slavenow takes aboost::program_options::variables_mapfrom which it will construct aslaveobject.This approach can also easily be extended to support the following variations:
Supporting multiple command-lines for a single value. For example, a configuration could support two slaves, with one of the slaves having a secondary configuration in case the first fails. This requires performing an initial tokenization on the
,delimiter.Declaring the options for
slave_descastyped_valuewith variables provided to thestore_toargument. These same variables can then be bound withboost::refviaboost::bindto themake_slavefactory function. While this decouplesmake_slavefrom Boost.ProgramOptions types, it may become difficult to maintain for types with many fields.Alternatives Approaches
Alternative approaches still need explicit pairing to be done via placing multiple values into a single value. However, transformations can occur during the parsing phase by inheriting from either
boost::program_options::typed_valueorboost::program_options::untyped_value.typed_value, override theparsefunction. One consequence of usingtyped_valueis that the template parameter must meet all the requirements fortyped_value. For example, iftyped_value< slave >was used, then it would require makingslavedefault constructable, and defining bothistreamextraction (>>) andostreaminsertion (<<) operators forslave.untyped_value, override both theparseandnotifyfunctions. This approach does not impose type requirements liketyped_value, but it does require that the derived class maintain its ownstore_tovariable.Suggestions