1

i was doing some tests of the move semantics and I tried this :

class A{
public:
    A(){printf("A CTOR\n");}
    A(A&) {printf("A CTOR by copy\n");}
    A(A&&){printf("A CTOR by universal reverence\n");}
};

A&& create(){
    A v;
    return std::move(v);
}

auto x{ create() };//this does not compile

float d[]{1.2,1.3,5,6};//this does compile

I get the following error:

error C3086: cannot find 'std::initializer_list': you need to #include <initializer_list>

I don't understand as the initializer list feature has been added to VC11 with CTP2012 nov. Is this because we have to wait for an update of the stdlib ?

I think the code is correct as I copied it from a slide from Scott meyers: Move Semantics, Rvalue References, Perfect Forwarding.

Thank you for your help. For your information, the spurious copies occured because i did not add "const" in my CTOR by copy. Best

ildjarn
  • 62,044
  • 9
  • 127
  • 211
dzada
  • 5,344
  • 5
  • 29
  • 37
  • I have this error : 1>c:\users\adrien\documents\visual studio 2012\projects\consoleapplication2\consoleapplication2\consoleapplication2.cpp(50): error C3086: cannot find 'std::initializer_list': you need to #include I tried to add this header but it does not exist. It was removed in VS10 and I think this header should ,not exist as it is a core feature; – dzada Nov 07 '12 at 09:17

2 Answers2

6

Braces with auto will always end up in std::initializer_list<T> type. So basically what happens here you try to create a std::initializer_list<A> here for x instead of A what probably was your intent here. However your code should compile fine and that may be a bug in the VS latest CTP compiler.

To make x be of A you have 2 options:

  1. Do not use auto here:

    A x{ create() };
    
  2. Do not use Uniform initialization here:

    auto x(create());
    

Beside that I see 2 other issues in you code. Firstly signature of proper copy-constructor should look like that:

A(const A &) {printf("A CTOR by copy\n");}

Moreover it is not encouraged to return RValue references from functions. Instead you should return by value like that:

A create(){
  A v;
  return v;   // std::move not needed here because C++11 compiler will put it for you here
}

or just:

A create(){
  return A();
}

EDIT:

Oh and just to be politically correct A(A&&) is not "A CTOR by universal reference". It is "A CTOR by move" or "A CTOR by rvalue reference" depending on which level of abstraction you want to operate. Universal reference is always about templates and that specific type type deduction.

Please also read an article of Scott Meyers I attached in a different comment http://scottmeyers.blogspot.com/2012/10/copying-constructors-in-c11.html where the same C++ guru that you refer in your notes exactly explains the problems you face. Hope that helps.

Mateusz Pusz
  • 1,363
  • 1
  • 9
  • 16
  • Hi yes indeed there should be a const. Also I tried this return by value, and It fails. It does copy even if I'm not sure of why yet, I thought it would have work but it does not. – dzada Nov 07 '12 at 10:33
  • and the auto x{create()}; is on page 8 http://www.aristeia.com/TalkNotes/ACCU2011_MoveSemantics.pdf I mean you are perhaps right, but it is just that I read it from here that makes me doubt. – dzada Nov 07 '12 at 10:35
  • Answering you first point. A copy may be needed in order to put a value inside the `initializer_list`. You can read more at http://scottmeyers.blogspot.com/2012/10/copying-constructors-in-c11.html. You will also find there an answer to your second concern. – Mateusz Pusz Nov 07 '12 at 10:47
  • @dzada See my updated answer: there are no unnecessary copies going on. – Ali Nov 07 '12 at 10:48
  • Yes I agree with you it looks like it should not copy but the copy CTOR is called. – dzada Nov 07 '12 at 14:57
  • 1
    @dzada Did you read Scott's article I refer? He describes there what is happening. It seems that some std::initializer_list implementations use copy constructors to initialize their content. On gcc 4.8 I did not see any copy-constructor if I return A by value. Only default constructor is called. – Mateusz Pusz Nov 07 '12 at 15:04
1

The line

auto x{ create() };//this does not compile

creates an initializer_list and not an instance of A, see for example std::initializer_list.

If you write

A x{ create() };

the code compiles and the type of x will be A.


I wouldn't return A&& from create(), see Move Semantics and Compiler Optimizations. I haven't seen this in Scott's slides either.


The following code prints only A CTOR, see here. That is the best you can get: The object has to be created. Apart from that there are no unnecessary copy constructor or assignment operator calls.

#include <cstdio>
#include <utility>
using namespace std;

class A{
public:
    A(){         printf("A CTOR\n");}
    A(const A&) {printf("A CTOR by copy\n");}
    A(A&&){      printf("A CTOR by universal reverence\n");}
    A& operator=(const A& ) = delete;
};

A create(){
    return A();
}

int main() {
    A x{ create() };
    return 0;
}

std::move is not the only way to get rid of the unnecessary copies. The compiler can do it for you, see for example What are copy elision and return value optimization? or Copy elision.

Community
  • 1
  • 1
Ali
  • 56,466
  • 29
  • 168
  • 265
  • the auto x{create()}; is on page 8 here http://www.aristeia.com/TalkNotes/ACCU2011_MoveSemantics.pdf – dzada Nov 07 '12 at 10:35
  • @dzada I meant: returning `A&&`. Do you have that somewhere in the slides? – Ali Nov 07 '12 at 10:36
  • I don't know in the slides, I did not find the presice definition of the crete function. So i tried, And my compiler gives the same error with A create(){A v;return v;} and return A() – dzada Nov 07 '12 at 10:59
  • @dzada Gives the same error for what? Did you try the code at the bottom of my updated answer? – Ali Nov 07 '12 at 11:30
  • yes exactly, i have the save error with create defined : A create() – dzada Nov 07 '12 at 12:22
  • @dzada It is not what I write. Please check my code again, I write: A x{ create() };. Just copy and paste my WHOLE code and see what you get. – Ali Nov 07 '12 at 12:26
  • @dzada OK, check it for yourself: my code is OK and does what I wrote: http://ideone.com/sqeOhA – Ali Nov 07 '12 at 12:31