c++ 带有if constexpr的模板化函数中未使用的参数警告

v09wglhw  于 2023-06-07  发布在  其他
关注(0)|答案(3)|浏览(209)

在这段代码中

#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
我的理解是,从逻辑上讲,方法的示例化是完全不同的。如果参数没有在模板的某个示例化中使用,那么它不是一个未使用的变量吗?或者语言/编译器不这样解释它。

vnjpjtjt

vnjpjtjt1#

出于同样的原因,在被丢弃的分支中不能有语法错误。
我假设你使用GCC和-Wextra,否则我不会得到未使用的参数警告。
请考虑以下代码:

void func(int arg) {
    if constexpr(false) {
        // discarded branch, so arg should be unused?
        static_cast<void>(arg);
    }
}

int main() {
    func(4);
}

如果注解掉static_cast,将得到警告unused parameter 'a'
如果你不使用static_cast,而是执行了一些不应该编译的操作,那么它就不会编译:

void func(int arg) {
    if constexpr(false) {
        int *p = arg; // invalid conversion from 'int' to 'int*'
    }
}

编译器查看整个函数,即使它没有示例化所有分支。这意味着没有像上面那样的错误。这也意味着,只有当参数在整个函数中的任何地方都没有使用时,才会抛出未使用参数警告。
¹在模板函数的情况下,表达式的有效性可能取决于变量的类型,函数中的所有表达式都必须在给定适当类型的情况下编译(这可能取决于if constexpr语句中的条件)。在丢弃语句中,对未定义实体的odr用法也有一种特殊情况。
完全检查丢弃的语句。if constexpr不能代替#if预处理指令。(cppreference

46qrfjad

46qrfjad2#

我们可以说参数a不是完全未使用的,它是 * 有条件地 * 未使用的。
C标准要求为格式错误的程序生成诊断消息。你的程序不是病态的。C标准根本不要求编译器生成其他警告。因此,由编译器供应商来决定如何实现它。
虽然我个人希望被警告有条件地未使用的变量(你的例子是一个很好的演示为什么),没有编译器供应商实现。为什么?他们在大型代码库上测试新版本的编译器,看看新的C特性是否会导致破坏性的变化。很可能,在这些测试中,像你这样的代码会产生很多警告,但CMaven认为这些代码完全没有问题。因此,对警告进行了调整,使其在此类情况下不会发生。这是为了确保代码可能有0个警告。

gmxoilav

gmxoilav3#

问题是“为什么编译器不警告else-s()中未使用的变量?(with -Wall)”
正如其他人所指出的,变量是在函数中使用的。它是有条件不使用的,如果你设置clang这样做,你会得到警告,正如cigien指出的那样:
次要的一点-GCC和Clang都不包含此警告。在Clang上,你会得到它与-Wextra至少。我建议编辑这个问题,只提到你正在询问的标志,即-Wunused-parameter。- cigien昨天
@ThomasWeller是对的,如果你向clang请求,有条件未使用的参数的警告是可用的。

相关问题