24

When using boost::program_options, how do I set the name of an argument for boost::program_options::value<>()?

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

int main()
{
  boost::program_options::options_description desc;

  desc.add_options()
    ("width", boost::program_options::value<int>(),
     "Give width");

  std::cout << desc << std::endl;

  return 0;
}

The above code gives:

  --width arg           Give width

What I want is to replace the arg name with something more descriptive like NUM:

  --width NUM           Give width
Tim Sylvester
  • 22,897
  • 2
  • 80
  • 94
Grumbel
  • 6,585
  • 6
  • 39
  • 50

6 Answers6

14

In recent versions of Boost (only tested for >= 1.61) this is fully supported. Below a slight modification of the first example in the tutorial, where "LEVEL" is printed instead of "arg":

po::options_description desc("Allowed options");
desc.add_options()
    ("help", "produce help message")
    ("compression", po::value<int>()->value_name("LEVEL"), "set compression level")
;

Live Example

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
9

The program_options::value_semantic class doesn't parameterize the argument name, so I think you will have to define your own class. Something like this:

struct my_arg_type
    : public boost::program_options::typed_value<int>
{
    my_arg_type(std::string const& name)
        : boost::program_options::typed_value<int>(&my_value)
        , my_name(name)
        , my_value(0)
    {
    }
    std::string name() const { return my_name; }
    std::string my_name;
    int my_value;
};

boost::program_options::options_description desc;

my_arg_type arg("foo");
desc.add_options()
    ("width", &arg, "give width");

This should give something like:

--witdh foo    give width
Tim Sylvester
  • 22,897
  • 2
  • 80
  • 94
  • 3
    The destructor for `boost::program_options::options_description` apparently tries to do a `free()` on `arg`, so I had to do `my_arg_type* arg = new my_arg_type("foo");` – eater Dec 20 '10 at 19:07
8

In the current version of boost (1.53) you don't need anymore to make your own class as Tim Sylvester proposed. It's possible to use : boost::program_options::typed_value. On which value_name can be configured.

#include <iostream>
#include <boost/program_options.hpp>
using boost::program_options::typed_value;
using boost::program_options::options_description;

int main(int argc, char **argv) {
    options_description desc("Usage");

    int someValue;
    auto someOption = new typed_value<decltype(someValue)>(&someValue);
    someOption->value_name("NUM");
    desc.add_options()
        ("some-option,s", someOption, "The option\n");

    std::cout << desc << std::endl;
    return 0;
}

Will display a configured argument name :

Usage:
-s [ --some-option ] NUM The option
daminetreg
  • 9,724
  • 1
  • 23
  • 15
  • 2
    So much for Vladimir's disdain for this kind of "micro-optimization". ;-) – DevSolar Apr 24 '13 at 08:07
  • Boost now has an `value()` overload that you can call `value_name()` on directly without doing "raw" `new`, see [my answer](http://stackoverflow.com/questions/1249646/when-using-boostprogram-options-how-does-one-set-the-name-of-the-argument/39934452#39934452) – TemplateRex Oct 09 '16 at 07:51
3

One can replace arg with something different via the global variable boost::program_options::arg:

boost::program_options::arg = "NUM";

But as that is a global variable, it doesn't help much to fix the problem when multiple option might require different arguments.

Grumbel
  • 6,585
  • 6
  • 39
  • 50
0

daminetreg's answer works, but it can be a little verbose when used for lots of option entries. I just hacked together an overload for the value<T>( T* v ) template to construct my value_sematics with an additional value_name: using

template<class T>
typed_value<T>*
value(T* v, const char * value_typename)
{
    typed_value<T>* r = new typed_value<T>(v);
    r->value_name( value_typename );

    return r;        
}

you can create and add a new program_option like this:

int width;
desc.add_options()
    ("width", boost::program_options::value<int>( &width, "NUM"),
     "Give width");

(Note: this doesn't address all the other construction templates, especially not the default value() constructor that the OP wants to use)

Community
  • 1
  • 1
Christian Severin
  • 1,793
  • 19
  • 38
  • Boost.Program_options now has this overload, see [my answer](http://stackoverflow.com/questions/1249646/when-using-boostprogram-options-how-does-one-set-the-name-of-the-argument/39934452#39934452)! – TemplateRex Oct 09 '16 at 07:49
-3

The approach given by Codebender is the only one you can use. This is actually intentional -- using "NUM" for name of argument appears to be micro-optimization that is not worth doing. A good description of the option should also say what kind of argument is expected.

Vladimir Prus
  • 4,600
  • 22
  • 31
  • 5
    Calling it "micro-optimization" is kind of stupid, considering that pretty much every single command line application on earth does it. I have yet to see a single one that doesn't give its arguments proper types or names. – Grumbel Aug 10 '09 at 12:51
  • Do you think that "stupid" is the right terminology to use when discussing potential changes with a maintainer of a free library? – Vladimir Prus Aug 10 '09 at 13:17
  • 1
    I just get a little pissed when peolpe tell me that a feature that is used by virtual every single command line application outthere is "not worth doing" in boost::program_options. – Grumbel Aug 10 '09 at 14:38
  • 3
    Be nice, guys. It's not something I would consider the least bit important, but whether a change is worthwhile is the sole decision of the person doing the work (or the person paying them). Call it a learning experience; that is the whole point of this site, after all. (BTW, Vladimir, your comments really should not be an "answer," which I suspect is the source of the down-voting.) – Tim Sylvester Aug 10 '09 at 16:59