【发布时间】:2015-02-11 16:14:10
【问题描述】:
我找不到编译时间间隔检查器,因此我尝试了一些方法来开发自己的方法,您应该在其中输入有问题的值、最小值和最大值,以便检查器在有问题的值在两个端点之间。
我的第一个方法是能够比较整数,它看起来像这样:
template<int Val, int LoEnd, int HiEnd>
struct is_in_interval : public std::integral_constant<bool, Val >= LoEnd && Val <= HiEnd>::type
{};
对函数的调用如下所示
bool inside = is_in_interval<3, 1, 10>::value;
这似乎奏效了。 如果低端高于高端,我什至可以让它在编译时失败:
template<int val, int LoEnd, int HiEnd>
struct is_in_interval : public std::integral_constant< typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type
{};
为了能够比较我想出的任何值:
template<typename T>
struct is_in
{
template<T val, T LoEnd, T HiEnd>
struct closed_interval : public std::integral_constant< typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type
{};
};
然而,现在这些电话变得更加晦涩:
bool inside = is_in<int>::closed_interval<3,1,10>::value;
但我仍然可以使用 enable_if,甚至可以添加更多功能(例如检查 is_integral)。
我的问题是,是否有可能通过从上面的非类型 (3,1,10) 中推导出类型 (int) 来使该通用版本更易于调用?
在我可以使用的旁注中:
template<typename T>
constexpr bool isInInterval3(T val, T LoEnd, T HiEnd)
{
return val >= LoEnd && val <= HiEnd;
}
但在那个函数中,我认为我不能使用std::enable_if 类型特征来断言LoEnd <= HiEnd。
【问题讨论】:
-
您仍然可以使用
isInInterval3进行编译时检查:constexpr bool assert_isIn(T const val, T const min, T const max) { return val >= min && val <= max ? true : throw "out of range"; }在需要常量表达式而不是异常的上下文中使用此类函数时,您将得到编译时错误。但这不是很有用;我宁愿在您当前的定义中使用static_assert(isInInterval3(val, lo, hi), "!!");。 -
@dyp 既不是对 SFINAE 友好,也不是一种优雅优雅的完成方式?
-
@Columbo 作为基本的构建块,我认为 OP 的
isInterval3很有用。您可以在此基础上构建 SFINAE 和硬错误。正如我所说,我认为我的assert_isIn不是很有用。 -
Related: stackoverflow.com/q/5628121 有很多这些问题与推断非类型模板参数的类型/某种接受所有类型的非类型参数有关。
-
@Columbo 顺便说一句,OP 对
enable_if的检查也不是 SFINAE(不在直接上下文中,因为它在基本子句中),因此可以用static_assert替换它。 (另外,检查lo < hi不需要 SFINAE 恕我直言,如果它失败,这是一个逻辑/编程错误。)
标签: c++ templates c++11 compile-time