Default value for vector valued boost::program_options
Asked Answered
W

1

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}?

Workbag answered 23/11, 2016 at 1:59 Comment(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.Jamestown
C
14

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");
Corum answered 28/11, 2016 at 22:30 Comment(4)
I've specified the operator std::ostream& operator<<(std::ostream &os, const std::vector<double> &vec){ for (size_t i=0; i<vec.size(); ++i){ os<< vec[i] <<" "; } return os; } but get the same error. What would the corresponding options entry be, assuming I've got the syntax in the OP wrong? Your "other approach" works for the default value, but no longer parses options given as "--vector_value=1 2 3".Workbag
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.Workbag
@Workbag Right, I've just added the missed ->multitoken() specifier to the code line above.Corum
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.Monostich

© 2022 - 2024 — McMap. All rights reserved.