如何处理由空模板参数包扩展引起的未使用警告?

dcm*_*m88 13 gcc clang compiler-warnings variadic-templates c++11

我一直面临的一个问题是编译器抱怨未使用的变量,即使使用了变量,但它仅用于特定实例化的参数包扩展中.例如:

template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
  auto var = get_tuple();
  return func2(std::get<I>(var)...);
}

auto a = func1(std::make_index_sequence<0>());
Run Code Online (Sandbox Code Playgroud)

查看实例(尝试在第4行更改元组,在<>中添加一个int以查看警告消失).我知道我可以添加(void)var;一行来使警告消失,但对我来说感觉很脏,特别是当函数实际上只是一行时.我也不想在全球范围内禁用此警告,因为它确实提供了有时的洞察力.

此问题的类似表现形式是在lambda捕获中使用变量时.在这种情况下,gcc没有发出警告,而clang抱怨(我认为gcc从未实现过关于未使用的lambda捕获的警告):

template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
  auto var = get_tuple();
  auto my_lambda = [var](){
    return func2(std::get<I>(var)...);
  };
  return my_lambda();
}

auto a = func1(std::make_index_sequence<0>());
Run Code Online (Sandbox Code Playgroud)

铿锵的例子

Rak*_*111 7

如果你可以使用C++ 17,那么[[maybe_unused]]属性是IMO最清晰的解决方案:

[[maybe_unused]]
auto tuple = get_tuple();
Run Code Online (Sandbox Code Playgroud)


Jar*_*d42 5

var确实没有用空包装.有意吗?编译器只能猜测.

虽然clang认为比空包更具用法,但gcc选择相反.

您可以通过不同方式使警告静音:

  • 属性[[maybe_unused]](C++ 17)
  • 铸造到void(static_cast<void>(arg))
  • 或类似的(template <typename T> void unused_var(T&&){}然后unused_var(var)).
  • 创建重载:

    auto func1(std::index_sequence<>)
    {
      return func2();
    }
    
    template <std::size_t... I>
    auto func1(std::index_sequence<I...>)
    {
      auto var = get_tuple();
      return func2(std::get<I>(var)...);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    或者在C++中17

    template <std::size_t... I>
    auto func1(std::index_sequence<I...>)
    {
        if constexpr (sizeof ...(I) == 0) {
            return func2();
        } else {
            auto var = get_tuple();
            return func2(std::get<I>(var)...);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 对于无效的c风格演员是少数几种C风格的演员阵容可以证明不会做坏事的案例之一.另外,如果不小心使用,`unused_var`可能会意外强制ODR存在变量. (2认同)

Tra*_*kel 3

这似乎是 GCC 中的编译器错误。最简单的解决方法是用 进行var标记[[gnu::unused]]

template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
  auto var [[gnu::unused]] = get_tuple();
  return func2(std::get<I>(var)...);
}
Run Code Online (Sandbox Code Playgroud)

如果您被迫使用无法识别的编译器[[gnu::unused]],您可以通过以下方式假装使用该变量static_cast<void>

template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
  auto var = get_tuple();
  static_cast<void>(var);
  return func2(std::get<I>(var)...);
}
Run Code Online (Sandbox Code Playgroud)

  • 无法识别的属性不会也会发出警告吗?[像这样](https://godbolt.org/g/oz9cwR) (3认同)