我试图简化在编译时检查将一个值转换为新类型是否保留该值的过程。 STL中可能有一些可以帮我实现的功能,但是我看不到,所以我写了一个。它可以工作,但我想将其转换为类,以使其他人的使用更加简单。我无法使它正常工作,感觉好像缺少明显的东西。
这很好:
template <typename T, typename Q>
constexpr bool checkV(const Q x)
{return x == (T)x && ((x < 0) == ((T)x < 0));}
static_assert(checkV<unsigned int>(-7), "No");
但是通话很麻烦,所以我想要更多类似的东西
CheckIt<unsigned int>(-7)
所以我尝试了
template<typename T>
class CheckIt {public:
template<typename Q>
constexpr CheckIt(const Q x) {static_assert(checkV<T>(x), "No");}
};
我尝试了const和constexpr的各种组合(发现的参数不能是constexprs,这很烦人)。我尝试的所有操作都会导致g ++抱怨x在构造函数中不是常量表达式。
我想念什么? checkv和构造函数都总是使用常量来调用,例如-7。 checkv()很高兴在编译时进行评估,我看不出在哪里使用构造函数进行包装,这会给编译器增加任何额外的负担,但显然可以。请注意,我需要在C ++ 11中使用它,但是我看不到更高版本的帮助。我在使用assert在运行时检查时没有问题,但是我想要常量的编译时解决方案。 TIA。
答案 0 :(得分:1)
将变量传递给函数将不起作用,因为它不是常量表达式,因此static_assert不会接受它。
您可以尝试将值作为模板参数传递。
template <typename T, typename Q>
constexpr bool checkV(const Q x)
{
return x == static_cast<T>(x) && ((x < 0) == (static_cast<T>(x) < 0));
}
template <typename T, typename Q, Q N>
void CheckIt() {
static_assert(checkV<T, Q>(N));
}
int main() {
constexpr auto val = -7;
CheckIt<unsigned int, decltype(val), val>();
}
但是它并不干净。
编辑:您还可以使用“好”的旧宏
#define CheckIt(x,y) static_assert(checkV<x, decltype(y)>(y));
int main() {
CheckIt(unsigned int, -7);
}