“警告:比较总是正确的”

Posted

技术标签:

【中文标题】“警告:比较总是正确的”【英文标题】:“Warning: comparison is always true” 【发布时间】:2013-01-19 23:20:39 【问题描述】:

带有-Wextra 的GCC (4.7.2) 发出以下警告/错误信号(我启用了-Werror):

由于数据类型[-Wtype-limits]的范围有限,比较总是正确的

对于以下代码 [try online]:

template <
    typename T,
    std::size_t N,
    bool = static_cast<std::size_t>(std::numeric_limits<T>::max()) < N>
struct validator 
    static constexpr bool validate(T value) 
        return static_cast<std::size_t>(value) < N;
    
;

template <typename T, std::size_t N>
struct validator<T, N, true> 
    static constexpr bool validate(T) 
        return true;
    
;

int main() 
    // Works
    static_assert(validator<int, 4>::validate(3), "Invalid");
    // Error :-(
    static_assert(validator<bool, 2>::validate(true), "Invalid");

我理解为什么在正常的表达式上下文中会出现警告,例如当我会使用以下validate 函数时:

template <typename T, std::size_t N>
bool validate(T value) 
    return static_cast<std::size_t>(value) < N;

– 事实上,这就是我首先使用专门模板的原因(请注意,使用了正确的模板专门化,并且我的第一个代码中的错误是由模板参数引发的,而不是在非专业模板)。有没有办法绕过这个警告?如果没有,那不是编译器的错误吗?

【问题讨论】:

我想你可以通过专门针对N 超过T 的最大值并让validate 返回true 的情况来解决这个问题。 我认为这是说 bool 不是 0 就是 1,所以所有 bool 都小于 2。 我的 gcc 4.7.2-2 在我尝试这个时没有发出警告,尽管我可能使用了错误的包含。 @Neil,你需要-Wtype-limits-Wextra @KerrekSB 这不是我在做什么吗? 【参考方案1】:

这已在 GCC 主干中修复,请参阅 PR 11856

所以请等待大约 4 月下旬并使用 GCC 4.8 :-)

【讨论】:

【参考方案2】:

由于我等不及解决此问题(请参阅 Jonathan 的回答),我已选择性地使用 GCC #pragma 扩展禁用警告:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
static_assert(validator<bool, 2>::validate(true), "Invalid");
#pragma GCC diagnostic pop

请注意,尽管实际错误发生在模板参数中,但不幸的是,这些 pragma 需要围绕 调用 代码。

【讨论】:

【参考方案3】:

这里有一个解决方法:

template <
    typename T,
    std::size_t N,
    bool = static_cast<std::size_t>(std::numeric_limits<T>::max()) < N>
struct validator 
    static constexpr bool validate(T value) 
        return size_t_cast(value) < N;
    
private:
    static constexpr std::size_t size_t_cast(T value) 
        return value;
    
;

template <typename T, std::size_t N>
struct validator<T, N, true> 
    static constexpr bool validate(T) 
        return true;
    
;

这允许示例在 GCC 4.7.2 中无错误地编译。

【讨论】:

不,这等同于我的代码并且具有相同的警告(您忘记启用-Wextra!)请注意,就像我在问题中所说的那样,警告不是由函数体产生的– 它是由模板实例化产生的。另一方面,起作用的是在结构之外定义size_t_cast,然后在模板列表中使用它。或者,实际上,没有现在多余的整个结构。 在这种情况下,再次测试。您的代码确实会产生相同的警告。 @KonradRudolph 有趣,我尝试了你的在线评估链接,我同意我本地安装的 gcc 给出了不同的结果,并且以你描述的方式应用 size_t_cast 对于在线版本是必要的。跨度>

以上是关于“警告:比较总是正确的”的主要内容,如果未能解决你的问题,请参考以下文章

在正确的位置获取正确的数据

应用程序无法启动并行配置不正确,小编教你应用程序无法启动并行配置不正确该怎么解决

如何正确 压测 swoole

JS脚本:正确性验证

脚本是不是正确1

关于存储容量,下列哪个说法是正确的?