编译时间间隔检查器
Posted
技术标签:
【中文标题】编译时间间隔检查器【英文标题】:Compile time interval checker 【发布时间】: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: ***.com/q/5628121 有很多这些问题与推断非类型模板参数的类型/某种接受所有类型的非类型参数有关。
@Columbo 顺便说一句,OP 对enable_if
的检查也不是 SFINAE(不在直接上下文中,因为它在基本子句中),因此可以用 static_assert
替换它。 (另外,检查 lo < hi
不需要 SFINAE 恕我直言,如果它失败,这是一个逻辑/编程错误。)
【参考方案1】:
您可以在一个模板中同时指定 'typename T' 和其他参数:
template<typename T, T val, T LoEnd, T HiEnd>
struct is_in_interval : public std::integral_constant<
typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type
;
然后,您可以定义一个只有 val、LoEnd 和 HiEnd 参数的宏 in_interval
,它将使用第一个模板参数调用 is_in_interval
,例如,decltype(val)
:
#define in_interval(val, LoEnd, HiEnd) (is_in_interval<decltype(val), val, LoEnd, HiEnd>::value)
你可以按如下方式使用它:
cout << in_interval(3, 1, 10) << endl;
这一切都适用于我的 VS2012
【讨论】:
以上是关于编译时间间隔检查器的主要内容,如果未能解决你的问题,请参考以下文章