mercredi 13 février 2019

Separating internal and external constructors with the same set of parameters

I have a type that takes a value, checks it against the type's parameters, and from that point on allows the value to carry around that check as an invariant. The type also has a number of operations associated with it that create new values of that type. All those operations are defined so that the check is not needed. There is no way once the user's value is in the type to ever have an invalid value of that type.

What I need is two constructors: one internal and one external. The external constructor should perform the check, while the internal constructor should not. They otherwise have the same parameters, the only difference is the check, which is the main issue. The check is avoided for performance reasons. Below is a mocked up example.

#include <stdexcept>

template <int limit>
class ClippedValue;

template <int limit>
void check(ClippedValue<limit> v) {
    if (std::abs(v.value) > limit) {
        make_user_solve_P_eq_NP();
        throw std::range_error("Given value exceeds available range");
    }
}

template <int limit>
class ClippedValue {
public:  // external constructor
    constexpr ClippedValue(int a) : value(a) { check(*this); }
private:  // internal constructor
    constexpr ClippedValue(int a) : value(a) {}
public:  // members
    const int value;
public:  // friends
    template <int A, int B>
    friend constexpr ClippedValue<A + B> operator+ (ClippedValue<A> a, ClippedValue<B> b);
}

template <int A, int B>
constexpr ClippedValue<A + B> operator+ (ClippedValue<A> a, ClippedValue<B> b) {
    return a.value + b.value;
}

The above doesn't compile, the two constructors are identical.

Aucun commentaire:

Enregistrer un commentaire