编译时间间隔检查器

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 &lt;= HiEnd

【问题讨论】:

您仍然可以使用isInInterval3 进行编译时检查:constexpr bool assert_isIn(T const val, T const min, T const max) return val &gt;= min &amp;&amp; val &lt;= 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 &lt; 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

【讨论】:

以上是关于编译时间间隔检查器的主要内容,如果未能解决你的问题,请参考以下文章

实现编译时机制检查字符串的唯一性

1.预处理器,编译器,汇编器和链接器

GLSL 着色器未编译,没有错误消息

如何检查该函数在编译器上是不是可用?

编译和运行

编译器会优化模板布尔值吗?