0

I'm trying to use auto for all local variables inside my functions.

Take the following code:

class obj 
{
  public:
  obj() {};
  obj( obj&& o ) = delete;
};

int main()
{
  obj test0;
  auto test1 = obj();

  return 0;
}

Compiling the code:

$ g++ --std=c++1z main.cpp
main.cpp: In function ‘int main()’:
main.cpp:13:20: error: use of deleted function ‘obj::obj(obj&&)’
   auto test1 = obj();

Notice that defining test0 is completely okay, but attempting to do the exact same type of declaration of test1 is a compiler error. Clearly is should be a compiler error, but in this case, does it mean obj can't be defined with auto? I'm running into this problem with QT objects I don't have control over.

Am I suck still using the C++98 format for declaring variables or is there another way to use auto?

Thanks!!!

vsoftco
  • 55,410
  • 12
  • 139
  • 252
Luke Dupin
  • 2,275
  • 23
  • 30
  • 1
    With `auto test1 = obj();`, you are using "copy initialization". However, `obj` is neither copy constructible (it has a move constructor declared, preventing the implicit generation of the copy constructor) nor move constructible (it is declared as deleted). – KABoissonneault Sep 16 '16 at 17:12
  • To prevent such traps in the future, consider using C++'s "Rule of 5" – KABoissonneault Sep 16 '16 at 17:13
  • Thank you, I understand what is happening and why it doesn't work. My question was, can auto be used with a class like this? If so how. – Luke Dupin Sep 16 '16 at 17:16
  • 1
    those two lines are not doing the exact same thing at all. Actually I dont know any circumstances under which a declaration `obj test0;` could fail to compile while I could imagine lots of reasons why `auto test1 = obj();` fails to compile – 463035818_is_not_an_ai Sep 16 '16 at 17:16
  • obj test0 would fail to compile if obj() constructor was private. – Luke Dupin Sep 16 '16 at 17:17
  • 1
    @LukeDupin oh of course, what a stupid comment... – 463035818_is_not_an_ai Sep 16 '16 at 17:28

3 Answers3

5

This is OK in C++17; guaranteed copy elision adjusts the rules so that a move constructor isn't even conceptually called, so it doesn't matter if it's deleted or inaccessible.

Before then, if you love auto so much, you can do

auto&& test1 = obj();

This creates a temporary obj object and binds it to the reference test1, extending its lifetime to that of the reference. With a few exceptions, the behavior is pretty much identical to what you will get in C++17 with plain auto.

T.C.
  • 133,968
  • 17
  • 288
  • 421
3

In the declaration

auto test1 = obj();

the compiler tries to move the object on the rhs, as it is a rvalue. It cannot (as the move ctor is marked as deleted). Note that because the move ctor is deleted, then the copy ctor is deleted as well, although the compiler will only try to move (because the move ctor, even though deleted, it is still consider user-defined and it is selected as a candidate during overload resolution). Hence, your code doesn't compile.

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
3

The error has nothing to do with the use of auto specifically.

obj test1 = obj();

doesn't compile as well. obj() is a r-value, that the compiler tries to move but the move constructor is deleted. Deleting the move constructor prevents the compiler of creating a copy constructor as well, so it can't copy it too, hence the error.

hlscalon
  • 7,304
  • 4
  • 33
  • 40