Boost program options setting min and max value for option
Asked Answered
P

3

8

Is it possible to set minimum and maximum limit of a value (suppose it is unsigned short and I need a value between 0 and 10) as I can set default value by

opt::value<unsigned short>()->default_value(5)

I want to use arguments given from variables map of program options immediately without checking each of them.

Pyrrhuloxia answered 28/8, 2014 at 11:50 Comment(0)
C
9

No, you cannot. All options are described here. You can check them manually, or write function, that will check them manually.

opt::value<unsigned short>()->default_value(5)->notifier(&check_function);

where check function is something like

void check(unsigned short value)
{
   if (value < 0 || value > 10)
   {
      // throw exception
   }
}

or more general

template<typename T>
void check_range(const T& value, const T& min, const T& max)
{
   if (value < min || value > max)
   {
      // throw exception
   }
}

opt::value<unsigned short>()->default_value(5)->notifier
(boost::bind(&check_range<unsigned short>, _1, 0, 10));
Chamois answered 28/8, 2014 at 11:57 Comment(1)
It doesn't seem like you can use this to check if the input is out of range for the type, for example passing -1 to an value<unsigned> is still passed as 4294967295 to the notifier function, unless being very careful with the type to "cast" it back to something. Optimally I would like to fail on any input that is out of range for the specified type.Bracteate
L
11

I recommend a lambda (like kaveish's answer). But you can have it return a function that checks the appropriate bounds to make everything more readable.

auto in = [](int min, int max, char const * const opt_name){
  return [opt_name, min, max](unsigned short v){ 
    if(v < min || v > max){ 
      throw opt::validation_error
        (opt::validation_error::invalid_option_value,
         opt_name, std::to_string(v));
    }
  };
};

opt::value<unsigned short>()->default_value(5)
  ->notifier(in(0, 10, "my_opt"));
Langton answered 23/2, 2015 at 4:57 Comment(1)
I like this solution a lot. Once minor tweak - I made in a template function with the type of min, max, and v as the template parameter.Butte
W
10

In C++11 this can also be achieved using lambda expressions.

opt::value<unsigned short>()
  ->default_value(5)
  ->notifier(
      [](std::size_t value)
      {
        if (value < 0 || value > 10) {
          // throw exception
        }
      })

This handily keeps the validation code itself close to the call point and allows you to customize the exception easier, something like

throw opt::validation_error(
  opt::validation_error::invalid_option_value,
  "option_name",
  std::to_string(value));
Walworth answered 6/11, 2014 at 2:10 Comment(0)
C
9

No, you cannot. All options are described here. You can check them manually, or write function, that will check them manually.

opt::value<unsigned short>()->default_value(5)->notifier(&check_function);

where check function is something like

void check(unsigned short value)
{
   if (value < 0 || value > 10)
   {
      // throw exception
   }
}

or more general

template<typename T>
void check_range(const T& value, const T& min, const T& max)
{
   if (value < min || value > max)
   {
      // throw exception
   }
}

opt::value<unsigned short>()->default_value(5)->notifier
(boost::bind(&check_range<unsigned short>, _1, 0, 10));
Chamois answered 28/8, 2014 at 11:57 Comment(1)
It doesn't seem like you can use this to check if the input is out of range for the type, for example passing -1 to an value<unsigned> is still passed as 4294967295 to the notifier function, unless being very careful with the type to "cast" it back to something. Optimally I would like to fail on any input that is out of range for the specified type.Bracteate

© 2022 - 2024 — McMap. All rights reserved.