Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate input parameters in C++ constructor?

Following example shows the crux of the problem. I need to initialize const members of a class. This can only be done in the initializer-list and not in constructor body. I want to assert or throw an error if input to the constructor is invalid, that is, if the vector size is less than 3.

class A {
 // In following constructor, how do we make sure if params.size()
 // is at least 3.
 A(const std::vector<int>& params):
  x(params[0]), y(params[1]), z(params[2]) {}
private:
  const int x;
  const int y;
  const int z;
};

Please advise how to achieve this in Modern C++ (11 and later)

like image 534
Punit Soni Avatar asked Dec 06 '18 20:12

Punit Soni


2 Answers

Just add a layer of abstraction. You can write a function that makes sure the vector is of the correct size and you can even make sure the values are in an expected range, if you have one. That would look like

class A {
 A(const std::vector<int>& params):
  x(verify(params, 0)), y(verify(params, 1)), z(verify(params, 3)) {}
private:
  static int verify(const std::vector<int>& params, int index) 
  { 
    if (params.size() < 4) // or use if (params.size() <= index) if you only care if the index will work
      throw something; 
    return params[index]; 
  }
  const int x;
  const int y;
  const int z;
};
like image 74
NathanOliver Avatar answered Sep 24 '22 19:09

NathanOliver


const members can only be initialized in the constructors's member initialization list. To validate the caller's input, you would have to call a helper function to validate each input value before passing it to the corresponding member, eg:

int check(const std::vector<int> &params, int index) {
  if (params.size() <= index) throw std::length_error("");
  return params[index];
}

class A {
 A(const std::vector<int>& params):
  x(check(params, 0)), y(check(params, 1)), z(check(params, 3)) {}
private:
  const int x;
  const int y;
  const int z;
};

Or, simply utilize the vector's own built-in bounds checking instead:

class A {
 A(const std::vector<int>& params):
  x(params.at(0)), y(params.at(1)), z(params.at(3)) {}
private:
  const int x;
  const int y;
  const int z;
};
like image 32
Remy Lebeau Avatar answered Sep 23 '22 19:09

Remy Lebeau