Topic: Another Move Constructor


Author: Mathias Gaunard <loufoque@gmail.com>
Date: Sat, 21 Aug 2010 22:01:59 CST
Raw View
On Aug 21, 12:04 am, w...@seed.net.tw wrote:
> A real proof is that the move
>   constructor can enable the definition of a general purpose no throw
> swap
>   function template

Move constructors are allowed to throw. This was decided because it
can be fairly difficult to provide a nothrow one in certain situations
(i.e. a tuple of types where some have a move constructor and some
don't).
Plus not all objects have a move constructor, some just have a copy
constructor, and in that case this is what gets invoked when trying to
move.


>   struct S {
>     S(S& src, ByMove_t);            // My move constructor, for
> instance.
>
>     S(type_store<T>& src) nothrow();   // Also a move constructor and
>     operator=(type_store<T>& src) ;   // a move assignment.
>   };
>
>   template<typename T>
>   void swap(T& a, T& b) throw() {
>     type_store<T> tmp;  // tmp is just a memory aligned buffer
> suitable for
>                         // storing type T. Constructor and destructor
> of T are
>                         // not called.
>     new(&tmp) T( static_cast<type_store<T>&>(a) );  // move a to tmp
>     new(&a)   T( static_cast<type_store<T>&>(b) );  // move b to a
>     new(&b)   T(tmp);                               // move tmp to b
>   };

It is indeed possible to implement move semantics as a library, except
you can't really detect rvalues (albeit there are hacks to do so).
Your solution, however, has many caveats and doesn't integrate with
existing code at all.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: wij@seed.net.tw
Date: Fri, 20 Aug 2010 17:04:03 CST
Raw View
Hi:
I have just written a document for my move constructor:

 "The motivation of devising is from the need to avoid costly and
unnecessary
  copy operations found in classes that contain allocated resources
and the
  object movements in a dynamic array. The move constructor is
defined to
  move the source referenced object to 'this' pointed address (source
object
  is automatically non-existent).
  It has been practiced that such motivation can be done by just
providing an
  expression "enum ByMove_t { ByMove };" and an explanatory theory
are enough
  for program to build/use the move constructor.

  ......., such a move constructor can exist
  as a general property of all objects. A real proof is that the move
  constructor can enable the definition of a general purpose no throw
swap
  function template (note: implementation requires a buffer type,
e.g.
  type_store<T>, but this is a different issue).
  ...[snip]"

Then, look again N3092 draft to realize that rvalue reference is a
reference of
temporary or literal object (I don't really understand many
terminologies of
the standard) and the moved source object can be destructed. I think
it better
asking these questions first.

  1. The implement of the rvalue reference based move constructor is
not
     much different from performing a swap function, as I can
understand.
  2. Rvalue reference looks like something belonging to the core-
language.
     Is it that elementary enough to trim the core part of the
language?
     (by using &&)

Whatever, from my point of view, the function of rvalue reference can
also be
done by using type_store<T>, just to provide an alternative. No
mention of
temporary object is required for users.

  struct S {
    S(S& src, ByMove_t);            // My move constructor, for
instance.

    S(type_store<T>& src) nothrow();   // Also a move constructor and
    operator=(type_store<T>& src) ;   // a move assignment.
  };

  template<typename T>
  void swap(T& a, T& b) throw() {
    type_store<T> tmp;  // tmp is just a memory aligned buffer
suitable for
                        // storing type T. Constructor and destructor
of T are
                        // not called.
    new(&tmp) T( static_cast<type_store<T>&>(a) );  // move a to tmp
    new(&a)   T( static_cast<type_store<T>&>(b) );  // move b to a
    new(&b)   T(tmp);                               // move tmp to b
  };

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]