i有一种具有值的类型,将其按照类型的参数进行检查,从那时起,该值允许该值以不变性为单位。该类型还具有与之相关的许多操作,这些操作创建了该类型的新值。所有这些操作都是定义的,因此不需要检查。一旦用户的价值在类型的类型中都无法使用该类型的无效值。
我需要的是两个构造函数:一个内部和一个外部。外部构造函数应执行检查,而内部构造函数则不应执行。否则它们具有相同的参数,唯一的区别是检查,这是主要问题。出于绩效原因,避免了支票。以下是一个模拟的例子。
#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;
}
上面没有编译,两个构造函数是相同的。
上面没有编译,两个构造函数是相同的。
确实。如此区分它们。
enum class unchecked_t {};
constexpr ClippedValue(unchecked_t, int a) : value(a) {}
标准库本身经常使用此范式。它区分了过载,并且由于unchecked_t
及其种类可能会自行访问控制,因此可以使用更精细的粒度可访问性规范,例如使用密钥 - 通用习惯。
正如您已经发现的那样,您不能有两个具有相同接口的构造函数。
您可以将一个虚拟参数添加到第二个构造函数中,以将其与第一个构造函数区分开。
template <int limit>
class ClippedValue
{
public:
// external constructor
constexpr ClippedValue(int a) : value(a) { check(*this); }
private:
// A type that can be used only internally and by friends of the class.
struct internal {};
// internal constructor. An overload.
// Use another argument, of type internal.
constexpr ClippedValue(int a, internal) : value(a) {}
...
};