997f6477   
   From: daniel.kruegler@googlemail.com   
      
   Am 02.04.2012 09:36, schrieb Brendan:   
   > Are members of r value references also considered r values?   
      
   I have difficulties understanding this question. An rvalue reference   
   itself has no members, so I must assume you speak of the properties of   
   some "expression". In this case, it is relevant whether the expression   
   is an lvalue expression or an rvalue expression. Note that it is only of   
   secondary relevance whether we speak of a variable that is an rvalue   
   reference. Details see below.   
      
   > In particulate, consider this Image class.   
   >   
   > typedef unsigned char Byte;   
   > typedef std::vector ImageVec;   
   >   
   > struct Image {   
   > Image(): m_width(0), m_height(0) {}   
   > Image(Byte* img_data, size_t width, size_t height):   
   > m_data(img_data, img_data + width * height * 3),   
   > m_width(width),   
   > m_height(height) {   
   > }   
   >   
   > Image(Image&& img):   
   > m_data(img.m_data),   
   > m_width(img.m_width),   
   > m_height(img.m_height){   
   > img.m_width = 0;   
   > img.m_height = 0;   
   > }   
   >   
   > Image& operator=(Image&& img) {   
   > if (this !=&img) {   
   > m_data = img.m_data;   
   > m_width = img.m_width;   
   > m_height = img.m_height;   
   > }   
   > return *this;   
   > }   
   >   
   > private:   
   > ImageVec m_data;   
   > size_t m_width;   
   > size_t m_height;   
   > };   
   >   
   > I'm wondering if the move constructor here can be expected to move the   
   > data from img.m_data to m_data, if I need to rewrite that as:   
   > m_data(std::move(img.m_data))   
   >   
   > Similarly, do I need to use std::move in the move assignment operator.   
      
   You need to use std::move to convert all your lvalues to rvalues. Within   
   the move-constructor and the move-assignment the expression "img" is an   
   lvalue. It does not matter what the underlying type of the declared   
   variable is. Now the follow-up question to clarify is: What is the   
   value-category of a member access expression (like "img.m_data") for a   
   variable of class type? Here we look at 5.2.5 [expr.ref] p4 and try to   
   deduce the value category of an expression E1.E2:   
      
   "If E2 is declared to have type “reference to T,” then E1.E2 is an lvalue;"   
      
   Is m_data a reference type? No, so we proceed with bullet 2 of   
   aforementioned paragraph:   
      
   "If E1 is an lvalue, then E1.E2 is an lvalue; if E1 is an xvalue, then   
   E1.E2 is an xvalue; otherwise, it is a prvalue."   
      
   E1 is an lvalue (it is a variable with a name), so E1.E2 is also an lvalue.   
      
   > Finally, I want to clarify my understanding of when implicit move   
   > constructors are generated. My understanding is that this changed   
   > during the standardization process.   
      
   Your assumption is correct.   
      
   > Could someone give a statement on   
   > exactly when implicit move constructors are generated in the final   
   > draft, perhaps with reference to section?   
      
   12.8 [class.copy] p9:   
      
   "If the definition of a class X does not explicitly declare a move   
   constructor, one will be implicitly declared as defaulted if and only if   
   — X does not have a user-declared copy constructor,   
   — X does not have a user-declared copy assignment operator,   
   — X does not have a user-declared move assignment operator,   
   — X does not have a user-declared destructor, and   
   — the move constructor would not be implicitly defined as deleted."   
      
   now you need to know when a move constructor will be deleted. This is   
   described in p11:   
      
   "A defaulted copy/move constructor for a class X is defined as deleted   
   (8.4.3) if X has:   
   — a variant member with a non-trivial corresponding constructor and X is   
   a union-like class,   
   — a non-static data member of class type M (or array thereof) that   
   cannot be copied/moved because overload resolution (13.3), as applied to   
   M’s corresponding constructor, results in an ambiguity or a function   
   that is deleted or inaccessible from the defaulted constructor,   
   — a direct or virtual base class B that cannot be copied/moved because   
   overload resolution (13.3), as applied to B’s corresponding constructor,   
   results in an ambiguity or a function that is deleted or   
   inaccessible from the defaulted constructor,   
   — any direct or virtual base class or non-static data member of a type   
   with a destructor that is deleted or inaccessible from the defaulted   
   constructor,   
   — for the copy constructor, a non-static data member of rvalue reference   
   type, or   
   — for the move constructor, a non-static data member or direct or   
   virtual base class with a type that does not have a move constructor and   
   is not trivially copyable.   
   "   
      
   > My understanding is that implicit move constructors would be generated   
   > in the scenario above.   
      
   You mean, if you would not have user-provided the move constructor and   
   the move assignment operator? In this case we look at your data members,   
   which are std::vector and std::size_t types, which are   
   all move-constructible. There is nothing in class Image that would   
   prevent the implicit declaration of the move-constructor and the   
   move-assignment operator.   
      
   > I'm actually kind of perturbed by that, because   
   > while the implicit copy constructor would be fine, the implicit move   
   > constructor would leave the source object in an invalid state.   
      
   Yes, this is one of the examples where the compiler-declared   
   move-constructor does the wrong thing.   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
    [ comp.lang.c++.moderated. First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|