“警告:比较总是正确的”
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
对于在线版本是必要的。跨度>
以上是关于“警告:比较总是正确的”的主要内容,如果未能解决你的问题,请参考以下文章