jeudi 20 juillet 2017

Pattern for Object Validation Logic in C++11

I want to ensure that the state of an object is always valid.

Let us assume a class with a constructor and a setter:

class MyClass {
  double x;  // Must be in [0;500].

public:

  MyClass(double _x) : x(_x) {
    if (x < 0.0)
      throw /*...*/;
    if (x > 500.0)
      throw /*...*/;
  }

  void SetX(double _x) {
    x = _x;
    if (x < 0.0)
      throw /*...*/;
    if (x > 500.0)
      throw /*...*/;
  }
};

This has several drawbacks:

  • The validation code is redundant. (in constructor & setter)
  • The rules exist for the class in general, and not only for specific methods. They should be specified inside the class but not inside a particular method.

Is it possible to do better with C++11/14/17 metaprogramming?

Ideally, the outcome would be similar to this:

class MyClass {
  double x;  // Must be in [0;500].

  /* Write all validation rules in a central place: */
  REGISTER_CONDITION(x, (x >= 0.0));
  REGISTER_CONDITION(x, (x <= 500.0));

public:

  MyClass(double _x) : x(_x) {
    validate(x);  // Tests all conditions that have been registered for x.
  }

  void SetX(double _x) {
    x = _x;
    validate(x);  // Tests all conditions that have been registered for x.
  }
};

Aucun commentaire:

Enregistrer un commentaire