home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 33,289 of 33,346   
   =?ISO-8859-2?Q?Daniel_Kr=FCgler?= to All   
   Re: auto-generated move assignment and b   
   27 Feb 14 06:09:09   
   
   From: daniel.kruegler@googlemail.com   
      
   Am 26.02.2014 14:42, schrieb Krzysztof Czaiński:   
   > On Monday, February 24, 2014 10:38:12 PM UTC+1, Daniel Krügler wrote:   
   >>>> Yes, this needs to be the case, because a operator= overload of the   
   > form   
   >>>>   
   >>>> T& T::operator=(T)   
   >>>>   
   >>>> was already a copy-assignment operator in previous versions of C++.   
   >   
   > But there were no move assignment operators, nor move constructors in   
   > previous C++.   
      
   Yes, but it still matters, because move operations where introduced as a   
   new species of special members in C++11 and all special members belong   
   exactly to one category, never to two.   
      
   > [...]   
   >   
   > Thank you for explaining this, Daniel, but this did not convince me.   
   > I will try to support my statement, that calling T& T::operator=( T ) is   
   > misleading.   
      
   Here seem to be a word missing, was this word "copy assignment operator"?   
      
   > Consider these classes:   
   >   
   > struct A // noncopyable   
   > {   
   >    A() = default;   
   >    A( A const& ) = delete;   
   >    A( A&& ) = delete; // this is redundant, here, isn't it?   
      
   It is redundant in the sense that without writing it, there will be no   
   implicit move-constructor declared for this class, because there exists   
   a user-declared copy-constructor (12.8 p9 b2).   
      
   >    A& operator=( A ) {}   
   > };   
   >   
   > An object of type A can't be copy assigned to or move assigned to,   
   > and yet in the same time it has a public "copy assignment operator".   
   > Come on, in practice A isn't copy assignable, nor move assignable!   
      
   You are mixing two different concepts here: One concept is the core   
   language concept of special member functions and these do specify that   
   this class has a copy-assignment operator. Having a copy-assignment that   
   also requires the existence of a move- or copy-constructor is not very   
   useful, though. But this is not very special for move operations. You   
   could alternatively declare the destructor as deleted without   
   introducing any deleted copy/move constructor and the type still would   
   not be able to copy-assign or even construct in a normal variable   
   definition.   
      
   The other concept is a an expression-based concept from the Standard   
   Library: Copy/MoveConstructible and Copy/MoveAssignable. Both concepts   
   are based on valid expressions, but they do not directly depend on the   
   existence of the core language special member functions. For example a   
   type without any special move member can still satisfy the   
   MoveConstructible or MoveAssignable concepts, if it has accessible and   
   non-deleted special copy member functions.   
      
   Trying to deduce from the existence (or absence) of special members (the   
   core language concept) the expression behaviour (the library concept),   
   is a false analogy and can lead to surprises. E.g. the following type   
   does have a deleted default constructor, but still can be   
   aggregate-initialized:   
      
   struct S {   
      S() = delete;   
   };   
      
   S s1; // Error   
   S s2{}; // OK, aggregate initialization   
      
   > struct B // movable only   
   > {   
   >    B() = default;   
   >    B( B const& ) = delete;   
   >    B( B&& ) = default;   
   >    B& operator=( B ) {}   
   > };   
   >   
   > An object of type B can't be copy assigned to, but can be move assigned   
   to,   
   > and yet in the same time it has a public "copy assignment operator".   
   > Come on, in practice B isn't copy assignable, but it is move assignable!   
      
   Again, you are mixing the two concepts I mentioned above.   
      
   > struct D // copyable and movable   
   > {   
   >    D() = default;   
   >    D( D const& ) = default;   
   >    D( C&& ) = default;   
   >    D& operator=( D ) {}   
   > };   
   >   
   > An object of type D can be copy assigned to and truly move assigned to.   
   > I mean truly move assigned, no copy occurs. But it has a public   
   > "copy assignment operator". Come on, in practice D is both copy assignable   
   > and move assignable.   
   >   
   > I wonder, what should the traits is_copy_assignable and is_move_assignable   
   > report for the above four classes?   
      
   These traits are referring to initialization forms and are not bound to   
   the existence or absence of special members. That was not always the   
   case. In fact the corresponding TR1 traits like has_trivial_copy,   
   has_trivial_assign, or has_nothrow_copy were in fact inspecting the   
   properties of special member functions. In this regard, the new   
   is_copy/move_* traits are testing "expression" semantics and are more   
   similar to the Library requirement sets (but do not impose behavioral   
   requirements) and are often considered as more useful. Still, we have   
   traits that solely inspect properties of core-language concepts, such as   
   is_trivial or is_trivially_copyable. For example, the following type is   
   trivially copyable, albeit it is not default-constructible,   
   copy/move-constructible, copy/move assignable nor destructible:   
      
   struct TC {   
      TC() = delete;   
      TC(const TC&) = delete;   
      TC(TC&&) = delete;   
      TC& operator=(TC&&) = delete;   
      TC& operator=(const TC&) = delete;   
      ~TC() = delete;   
   };   
      
   > As shown above, a class that has a "copy assignment operator" in practice   
   > behaves like it had other set of assignment operators (except for class   
   C).   
   > I call that misleading. I think it should be clearly stated, that   
   > any class that has T& operator=( T ) has:   
   > - a copy assignment operator iff it is copy constructable, and   
   > - a move assignment operator iff it is move constructable.   
   > (iff == if and only if)   
   >   
   > I hope this shows my concern better.   
      
   I have understood that your are comparing the core language definitions   
   of the special member functions with a different concept set. This was   
   the reason why I said in my previous response starting with "But I   
   understand the point that you are trying to make". Please keep in mind   
   that both concepts domains are different, albeit the core language   
   concept has impact on the outcome of the library concept.   
      
   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)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca