是否可以检查:
template<class IntType,IntType value>
struct X{};
我的意思是,是否可以检查用户提供的值是否“适合” IntType
(可以是任何标准整数类型)类型?例如,我想检测这样的事情:
X<char,300> a;//here 300 is out of range and I would like to be able to detect that.
是否可以检查:
template<class IntType,IntType value>
struct X{};
我的意思是,是否可以检查用户提供的值是否“适合” IntType
(可以是任何标准整数类型)类型?例如,我想检测这样的事情:
X<char,300> a;//here 300 is out of range and I would like to be able to detect that.
现在您已经更改X
了原始未编辑问题中的签名方式,可以使用Boost轻松实现。整数:
#include <boost/static_assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/integer_traits.hpp>
template<
typename IntType,
boost::uint64_t Value,
bool IsSigned = boost::integer_traits<IntType>::is_signed
>
struct validate_range;
template<typename IntType, boost::uint64_t Value>
struct validate_range<IntType, Value, true>
{
typedef boost::integer_traits<IntType> traits_t;
static bool const value =
static_cast<boost::int64_t>(Value) >= traits_t::const_min &&
static_cast<boost::int64_t>(Value) <= traits_t::const_max;
};
template<typename IntType, boost::uint64_t Value>
struct validate_range<IntType, Value, false>
{
typedef boost::integer_traits<IntType> traits_t;
static bool const value =
Value >= traits_t::const_min &&
Value <= traits_t::const_max;
};
template<typename IntType, boost::uint64_t Value>
struct X
{
BOOST_STATIC_ASSERT_MSG(
(validate_range<IntType, Value>::value),
"Value constant is out of range"
);
};
int main()
{
X<char, -2> x1; // fails iif char is unsigned by default
X<char, 2> x2; // fine
X<char, 255> x3; // fails iif char is signed by default
X<unsigned char, -2> x4; // fails
X<unsigned char, 255> x5; // fine
X<unsigned char, 300> x6; // fails
}
Boost 是正确的方法,但你真正想要的是新的 C++0x 标准即将到来的东西:静态断言。Boost 已经在boost_staticassert中实现了它。
不。给定您的代码,编译器会在您看到它之前300
将其转换为 a char
。
您可以做的最接近的事情是将参数接受为一个整数参数,该参数的范围大于您的目标类型。然后在转换之前检查该值是否合适。唯一的问题是signed
vs unsigned
,我认为没有通用的解决方案。
但不用担心:确保正确提供参数不是您班级的工作;那将是一个根本不存在的实用程序类型的工作。无论好坏,C++ 都没有为此提供干净的机制,因为它假定程序员不会犯这些错误。
我会说这个问题的直接解决方案可能是这样的:
template< typename T, T X, T L, T H>
using inside_t =
std::enable_if_t< (X <= H) && (X >= L),
std::integral_constant<T, X> >;
应用于OP:
template<typename C, unsigned K> struct X; // final {};
template<unsigned K>
struct X<char, K> final
{
using ascii_ordinal = inside_t<unsigned, K, 0, 127>;
char value = char(ascii_ordinal::value);
};
当它完成这项工作时,它会呈现非常糟糕的 CL 错误消息:
X<char, 300> a; //here 300 is out of range and I would like to be able to detect that.
虽然不那么时髦但最舒适的 API 可能是:
template<unsigned K>
struct X<char, K> final
{
static_assert( K >= 0U && K <= 127U, "\n\nTeribly sorry, but value must be between 0 and 127 inclusive\n\n") ;
char value = char(K);
};
在 C++20 中使用std::in_range
if constexpr (std::in_range<char>(300)) {
// ...
}
还有intcmp自己做比较
int val = 300;
if constexpr (std::cmp_greater(val, std::numeric_limits<char>::max()))
{
std::cout << "Overflow\n";
}
else if constexpr (std::cmp_less(val, std::numeric_limits<char>::min()))
{
std::cout << "Underflow\n";
}
else
{
std::cout << "In range\n";
}