Opened 10 years ago

Closed 6 years ago

#7418 closed Patches (wontfix)

Copyable and explicitly movable classes

Reported by: Daniel James Owned by: Ion Gaztañaga
Milestone: To Be Determined Component: move
Version: Boost 1.53.0 Severity: Problem
Keywords: Cc:

Description

Making a class movable can have some unfortunate side effects, as far as I know these are all due to implementing implicit moves. So if possible, it's be useful to have a class where the move mechanism only kicks in when boost::move is explicitly used. This could be efficient for cases where the class is explicitly moved (e.g. in a move enable vector), but avoid the potential problems.

I believe that this could be done by defining just the move construct and move assignment, but with no implicit conversions or other special functions. Then the main difficultly is modifying the has_move_emulation_enabled trait to support these types. Maybe the class could have a magic member typedef which is detected by sfinae, or maybe you can come up with something better.

Does this sound like a good idea? I haven't tried implementing it, so I might be missing some problem with the idea.

Attachments (1)

boost-move-1.53.diff (1.5 KB ) - added by KaiSt <k.stuhlemmer@…> 9 years ago.
Extending boost/move by macro BOOST_RV_REF_WRAPPER() for safer usage. Patch has been created against Boost 1.53

Download all attachments as: .zip

Change History (3)

by KaiSt <k.stuhlemmer@…>, 9 years ago

Attachment: boost-move-1.53.diff added

Extending boost/move by macro BOOST_RV_REF_WRAPPER() for safer usage. Patch has been created against Boost 1.53

comment:1 by KaiSt <k.stuhlemmer@…>, 9 years ago

Type: Feature RequestsPatches
Version: Boost 1.52.0Boost 1.53.0

Hi, I locally solved the problem in Boost 1.53. May changes are attached as "boost-move-1.53.diff". To be sure we are talking about the same problem, let me explain, which problem I see. Let's assume the following use case:

  class Movable
  {
    private:
      BOOST_MOVABLE_BUT_NOT_COPYABLE(Movable);
    public:
      Movable() : mNrMoves(0)
      { }

      Movable(BOOST_RV_REF(Movable) other)
      : mNrMoves(other.mNrMoves + 1)
      {
        other.mNrMoves = 0;
      }

      unsigned mNrMoves;
  };

  struct MovableUser
  {
    Movable m;

    MovableUser(BOOST_RV_REF_WRAPPER(Movable) mi)
    : m(boost::move(mi))
    { }
  };

If I use this implementation, pre-C++11 compiler users might use it with bad surprising behaviour:

  Movable m;
  MovableUser mu(m); // this silently compile wit pre-C++11 compiler, C++11 compiler correctly fails because of missing boost::move()

My fix just added a wrapper class for boost::rv and an accompanying macro BOOST_RV_REF_WRAPPER(). If You change Movable(BOOST_RV_REF(Movable) other) to Movable(BOOST_RV_REF_WRAPPER(Movable) other), then the example above also fails with pre-C++11 compiler enforcing the usage of boost::move():

  Movable m;
  MovableUser mu(boost::move(m)); // now correct

I hope, that helps. Please consider to add this patch or a similar solution to new releases.

comment:2 by Ion Gaztañaga, 6 years ago

Resolution: wontfix
Status: newclosed

Closing old bugs, this feature was not generally requested by users so closing as WONTFIX.

Note: See TracTickets for help on using tickets.