在这段代码中
#include <type_traits>
#include <iostream>
template <class T>
void func(const T& a)
{
if constexpr(std::is_same_v<T,int>)
{
static_cast<void>(a);
}
else if constexpr(std::is_same_v<T,double>)
{
// oops forgot to use it here
}
else
{
}
}
int main() {
func(4);
func("this");
}
为什么编译器不警告else-s()
中未使用的变量?(-Wall
)
我的理解是,从逻辑上讲,方法的示例化是完全不同的。如果参数没有在模板的某个示例化中使用,那么它不是一个未使用的变量吗?或者语言/编译器不这样解释它。
3条答案
按热度按时间vnjpjtjt1#
出于同样的原因,在被丢弃的分支中不能有语法错误。
我假设你使用GCC和
-Wextra
,否则我不会得到未使用的参数警告。请考虑以下代码:
如果注解掉
static_cast
,将得到警告unused parameter 'a'
。如果你不使用
static_cast
,而是执行了一些不应该编译的操作,那么它就不会编译:编译器查看整个函数,即使它没有示例化所有分支。这意味着没有像上面那样的错误。这也意味着,只有当参数在整个函数中的任何地方都没有使用时,才会抛出未使用参数警告。
¹在模板函数的情况下,表达式的有效性可能取决于变量的类型,函数中的所有表达式都必须在给定适当类型的情况下编译(这可能取决于
if constexpr
语句中的条件)。在丢弃语句中,对未定义实体的odr用法也有一种特殊情况。完全检查丢弃的语句。
if constexpr
不能代替#if预处理指令。(cppreference)46qrfjad2#
我们可以说参数
a
不是完全未使用的,它是 * 有条件地 * 未使用的。C标准要求为格式错误的程序生成诊断消息。你的程序不是病态的。C标准根本不要求编译器生成其他警告。因此,由编译器供应商来决定如何实现它。
虽然我个人希望被警告有条件地未使用的变量(你的例子是一个很好的演示为什么),没有编译器供应商实现。为什么?他们在大型代码库上测试新版本的编译器,看看新的C特性是否会导致破坏性的变化。很可能,在这些测试中,像你这样的代码会产生很多警告,但CMaven认为这些代码完全没有问题。因此,对警告进行了调整,使其在此类情况下不会发生。这是为了确保代码可能有0个警告。
gmxoilav3#
问题是“为什么编译器不警告else-s()中未使用的变量?(with -Wall)”
正如其他人所指出的,变量是在函数中使用的。它是有条件不使用的,如果你设置clang这样做,你会得到警告,正如cigien指出的那样:
次要的一点-GCC和Clang都不包含此警告。在Clang上,你会得到它与-Wextra至少。我建议编辑这个问题,只提到你正在询问的标志,即-Wunused-parameter。- cigien昨天
@ThomasWeller是对的,如果你向clang请求,有条件未使用的参数的警告是可用的。