How to handle unused warnings caused by empty template parameter pack expansions?

若如初见. 提交于 2020-01-14 07:03:14

问题


An issue I keep facing is one where the compiler complains about an unused variable, even though the variable is used, but it's only used inside a parameter pack expansion that happens to be empty for a specific instantiation. For example:

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>());

See live example (try changing the tuple at line 4, by adding an int inside <> to see the warning go away). I know I could add a (void)var; line to make the warning go away, but it feels dirty to me, especially when the function is actually just a single line. I also don't want to disable this warning globally, because it does provide insight sometimes.

A similar manifestation of this issue is when the variable is used in a lambda capture. In this case, gcc spits no warning, while clang complains (I think gcc never implemented a warning about unused lambda captures):

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>());

clang example


回答1:


If you can use C++17, the [[maybe_unused]] attribute is the clearest solution IMO:

[[maybe_unused]]
auto tuple = get_tuple();



回答2:


var is indeed not use with empty pack. Is it intended ? compiler can only guess.

Whereas clang consider than empty pack is a usage, gcc chooses the contrary.

You can silent the warning in different ways as:

  • attribute [[maybe_unused]] (C++17)
  • casting to void (static_cast<void>(arg))
  • or similar (template <typename T> void unused_var(T&&){} and then unused_var(var)).
  • creating overloads:

    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)...);
    }
    

    or in 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)...);
        }
    }
    



回答3:


This seems to be a compiler bug in GCC. The easiest workaround is to mark var with [[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)...);
}

If you are force to use compilers that don't recognize [[gnu::unused]], you can fake use the variable with a 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)...);
}



回答4:


(void)var; suppressed unused warnings in every compiler I have used:

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

(void)variable; has zero run time effects.




回答5:


Maybe there are other problems but... according the code you linked in compiler explorer, your var is a std::tuple<>; that is a std::tuple with zero components.

If I'm not wrong, std::get<Num>(std::tuple<Ts..>) is defined only when Num is in [0,sizeof...(Ts)); in this case in [0, 0), that is an empty interval.

I suppose that your code (when var is defined as std::tuple<>) is ill formed. So I suppose that the warning is correct (because there isn't cases when var is used) but doesn't warn about the real problem.

It's different when var is defined as std::tuple<int>: var is correctly used when all I are equal to zero, so var is (potentially) used and, as you observed, the warning disappears.



来源:https://stackoverflow.com/questions/46473038/how-to-handle-unused-warnings-caused-by-empty-template-parameter-pack-expansions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!