10

I have a boost::program_options option that successfully parses the desired input options into a vector, but I'm not seeing how to also give it a default value. Example:

base.add_options()
 ("vector_value",po::value<std::vector<double> >(&vecoption)->multitoken(),"description");

works fine to read values into vecoptions, and something like

    base.add_options()
 ("int_value",po::value<int>(&intoption)->default_value(1),"description");

also works fine, but trying to give the vector argument a default value like in

base.add_options()
 ("vector_value",po::value<std::vector<double> >(&vecoption)->default_value(std::vector<double>{0,1,2}),"description");

gives a compiler error

error: static assertion failed: Source type is neither std::ostream`able nor std::wostream`able

How can I create a vector-valued float option with default values like {0,1,2}?

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
Aurelius
  • 1,146
  • 2
  • 13
  • 25
  • 1
    Unrelated, but you do not need to explicitly provide template arguments to `po::value`. Just `po::value(&intoption)` and `po::value(&vecoption)` are fine. It's a function template. – Barry Nov 29 '16 at 14:33

1 Answers1

13

Problem caused by missed operator<< for ostream for the type std::vector<double>. This operator required to provide textual representation of your default value. In the boost\program_options\value_semantic.hpp header you can find a comment about this requirement:

/** Specifies default value, which will be used if none is explicitly specified. The type 'T' should provide operator<< for ostream. */

typed_value* default_value(const T& v)

To solve the problem you can specify operator<< like:

namespace std
{
  std::ostream& operator<<(std::ostream &os, const std::vector<double> &vec) 
  {    
    for (auto item : vec) 
    { 
      os << item << " "; 
    } 
    return os; 
  }
} 

Boost is able to resolve the operator<< if it's defined in the namespace std. In this case default parameter value can be specified like:

("vector_value", po::value<std::vector<double> >(&vecoption)->multitoken()->default_value(std::vector<double>{0, 1, 2}), "description");  

The other approach is to use method with explicit textual value specification:

("vector_value", po::value<std::vector<double> >(&vecoption)->multitoken()->default_value(std::vector<double>{0, 1, 2}, "0, 1, 2"), "description");
Community
  • 1
  • 1
Nikita
  • 6,270
  • 2
  • 24
  • 37
  • I've specified the operator `std::ostream& operator<<(std::ostream &os, const std::vector &vec){ for (size_t i=0; i – Aurelius Nov 29 '16 at 22:42
  • Scratch the second part of above comment; with the textual representation the above works with ->default_value(...)->multitoken(). If you could edit your answer to show the ostream'able version I'll happily accept it. – Aurelius Nov 29 '16 at 23:00
  • @Aurelius Right, I've just added the missed `->multitoken()` specifier to the code line above. – Nikita Nov 29 '16 at 23:02
  • 2
    Isn't this Undefined Behavior? You're adding methods to `namespace std`. The only thing you can add to `std` are template specializations, and eve then only for your own methods. And you probably don't need to have it defined in `std` anyway, as the global namespace is always searched. – MSalters May 11 '17 at 08:49