Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uniform initialization with {} reporting unused variable

Compiling this code with g++ 4.7.0 (-Wall -Wextra -Werror -Wconversion -std=c++11):

#include <iostream>  // std::cout, std::endl
#include <string>    // std::string
#include <utility>   // std::move

void out(std::string const &message)
{
   static int count{0};
   std::cout << count++ << " = " << message << std::endl;
}

struct Foo
{
   Foo()                         {out("constructor");}
  ~Foo()                         {out("destructor");}
   Foo(Foo const &)              {out("copy constructor");}
   Foo & operator=(Foo const &)  {out("copy via assignment"); return *this;}
   Foo(Foo &&)                   {out("move constructor");}
   Foo & operator=(Foo &&)       {out("move via assignment"); return *this;}
};

int main()
{
   auto bar{std::move(Foo())};
   out("exiting main");
}

...results in the following error:

error: unused variable 'bar' [-Werror=unused-variable]

I can remove the error by changing the bar initialization to any of the following:

/* 0 */ auto bar(std::move(Foo()));
/* 1 */ Foo bar{std::move(Foo())};
/* 2 */ Foo bar(std::move(Foo()));
/* 3 */ auto bar = std::move(Foo());
/* 4 */ Foo bar = std::move(Foo());
/* 5 */ auto bar __attribute__((unused)) {std::move(Foo())};

Once the bar initialization has been changed, the output is always:

0 = constructor
1 = move constructor
2 = destructor
3 = exiting main
4 = destructor

Why does the original bar initialization report an unused variable?

like image 437
Matt Tardiff Avatar asked Mar 18 '12 16:03

Matt Tardiff


People also ask

What is uniform initialization in C++?

Uniform initialization is a feature in C++ 11 that allows the usage of a consistent syntax to initialize variables and objects ranging from primitive type to aggregates. In other words, it introduces brace-initialization that uses braces ({}) to enclose initializer values.

What are unused variables?

An unused variable refers to a variable of which the data element structure is unreferenced in the main program, including the parent and the subordinate items. An unused copybook refers to a copybook with the aforementioned copybook of an unused variable.


2 Answers

auto bar{std::move(Foo())};

After this declaration, bar is of type std::initializer_list<Foo>, which has trivial copy/move operations and destructor. Your other declarations

auto bar(std::move(Foo()));
Foo bar{std::move(Foo())};
Foo bar(std::move(Foo()));
auto bar = std::move(Foo());
Foo bar = std::move(Foo());

declare bar as Foo or Foo&&, which suppresses the warning since it has nontrivial special member functions.

You generally don't want braced initialization with auto unless you specifically intend to create a std::inializer_list object.

like image 62
Philipp Avatar answered Oct 07 '22 22:10

Philipp


Well, bar is unused. You may want to file a defect for the compiler as this seems to errornously go undetected in the other situations.

like image 26
Dietmar Kühl Avatar answered Oct 07 '22 21:10

Dietmar Kühl