如何标记 constexpr 函数的参数未使用?

How to mark a constexpr function's parameter unused?

本文关键字:参数 未使用 函数 何标记 constexpr      更新时间:2023-10-16

考虑这个经典的例子:

template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&array)[N]) noexcept { return N; }

现在可以正常工作了,但是有一个问题,gcc给出一个警告:

warning: unused parameter ‘array’ [-Wunused-parameter]
已知解决方案:

  • 不工作:如果我将经典的(void)arr;添加到函数中,我得到error: body of constexpr function ‘...‘ not a return-statement
  • 不满意:我可以有arraySize(T (&)[N]),但我想命名的论点有两个原因:
    1. 使编译器错误信息更容易理解。
    2. 更主观地说,我认为它使代码更清晰,特别是对于那些不生活和呼吸这种语法的人。
  • 不太好:在这个特殊的例子中,我也可以return sizeof(array)/sizeof(array[0]);,但这种方法不是通用的解决方案,而且我认为return N;更好,绝对更容易看。
  • 好,但并不总是可能的:切换到使用c++ 14和完全支持它的编译器。然后允许像{ (void)array; return N; }这样的constexpr函数体。

当使用c++ 11时,我如何很好地摆脱未使用的参数警告?

试试这个。我有时使用这个方法

template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (& /*array*/ )[N]) noexcept { return N; }

我建议下面(ab)使用逗号操作符:

return (void)array, N;

新用户:

c++ 17增加了[[maybe_unused]]属性,可以这样使用:

template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&array)[N] [[maybe_unused]]) noexcept { return N; }

最佳解决方案是第二点所禁止的,即使用T(&)[N]

根据注释,另一种可能的方法是使用以下返回值:
return array ? N : N;

我很确定编译器会摆脱它,在运行时不会有性能问题。

正如@fnc12和@skypjack都指出的那样,沉默未使用的参数编译器警告的惯用方法是不给参数命名。

constexpr std::size_t arraySize(T (& /*array*/ )[N]) noexcept { return N; }

使用/**/注释解决了可读性问题。它不会在编译器消息中修复名称,但我认为最有可能出现的情况是"未声明的标识符",一旦您注意到标识符被注释,这很容易解决。

如果你真的非常反对这种习惯的方式,那么就直接取消警告(如果你的编译器允许的话)。

在GCC中使用#pragma GCC diagnostic .

使用#pragma warning suppress在Visual Studio中抑制警告

我建议不要在代码中添加"虚拟"引用来关闭编译器。引用一个未被使用的参数只是为了抑制编译器的警告,这不必要地增加了代码的复杂性,并且可能会使未来的维护者对它的存在感到困惑。

gcc提供了未使用的属性,可以这样使用:

constexpr std::size_t arraySize(__attribute__((unused)) T (&array)[N]) noexcept { return N; }
                                ^^^^^^^^^^^^^^^^^^^^^^^

Ben Deane最近发了一条关于c++ 11使用lambdas和逗号操作符来抑制此警告的方法,它看起来像这样:

#define UNUSED(x) [&x]{}()
//...
return UNUSED(array), N;

未命名的参数是正确的解决方案。

所以你可以使用一个中间函数:
template <typename T>
constexpr void avoid_warning_for_unused_parameter(T&&) noexcept{}

然后:

template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&array)[N]) noexcept
{
    avoid_warning_for_unused_parameter(array);
    return N;
}

对于c++ 11,你需要做更多的修改:

template <typename... Ts>
constexpr auto return_first_and_avoid_warning_for_unused_parameters(T&&t, Ts&&) noexcept
-> decltype(t)
{
    return t;
}
template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&array)[N]) noexcept
{
    return return_first_and_avoid_warning_for_unused_parameters(N, array);
}