想到了两种方法:
为“签名”类型添加显式转换。
#include <cassert>
class A {
unsigned int x;
public:
A(unsigned int X) : x(X) {}
explicit A(int X) : x(static_cast<unsigned>(X)) {
assert(X>=0); // note X, not x!
}
};
int main()
{
A ok(5);
A bad(-5);
}
通过删除更好的重载来禁止隐式转换:
A(int X) = delete;
A(long X) = delete;
A(char X) = delete;
这将要求所有用户在构造 A 实例之前强制转换为无符号。它安全但笨拙。
请注意,这并不禁止来自所有整数类型(例如s)的隐式转换,enum
因此您需要做更多的工作来证明这一点。
这是一个基于 SFINAE 的基本示例,它接受所有隐式转换,除非它们涉及有符号值:Live on Coliru
#include <type_traits>
#include <limits>
class A {
unsigned int x;
public:
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value, void>::type>
A(T X) : x(X)
{
static_assert(!std::numeric_limits<T>::is_signed, "Signed types cannot be accepted");
}
};
int main()
{
A ok(5u);
A bad(-5);
}