C++11 feature proposal: Move-only constructors

370 views
Skip to first unread message

Dana Jansens

unread,
Sep 24, 2014, 5:52:34 PM9/24/14
to chromium-dev
Hello,

I would like to propose that we allow move-only constructors for our classes. They look like this:

class Foo {
  Foo(Foo&& other) { ... }
}

Here Foo can only be constructed from another Foo that is an rvalue (ie it doesn't have a name of its own in the code).

I'd like to propose this specifically because I believe that nullptr support in scoped_ptr is not possible without it. That points to this being a very useful construct.




-- More below the fold --

Here's gritty details about why scoped_ptr + nullptr can't happen without a move-only constructor (I think):

scoped_ptr<int> Function() {
  return nullptr;
}

scoped_ptr<int> var = Function();

This function requires a constructor that turns the nullptr into a scoped_ptr<int> to compile. But then when we try to construct var, it tries to use the private copy constructor, which does not work.

scoped_ptr<int> Function2() {
  return scoped_ptr<>;
}

I believe Function2 works because you have an explicit scoped_ptr, which we return. Then when we create var, it will do an implicit conversion from scoped_ptr<> to RValue, and scoped_ptr has a constructor from RValue.

But if we use that implicit conversion inside Function to go from nullptr to scoped_ptr<>, we're unable to produce an RValue in order to make var. So this is not possible without 2 implicit conversions, or using a move constructor on scoped_ptr.

Any solution without a move constructor needs to create an explicit scoped_ptr<> inside Function() to return, which means you're just making sugar for scoped_ptr<>(), and really this has nothing to do with nullptr anymore.

Hendrik

unread,
Sep 24, 2014, 5:57:54 PM9/24/14
to chromi...@chromium.org
+1

Nico Weber

unread,
Sep 24, 2014, 5:58:37 PM9/24/14
to Dana Jansens, chromium-dev
I feel pretty strongly that we shouldn't allow anything that has something to do with rvalue references for a while, since as far as I can tell they aren't understand by many folks.

Having said that, I think it makes sense to make an exception to this for a few classes in base (scoped_ptr, probably the bind stuff), where using the feature (here: being able to write "return nullptr;" in a function that returns a scoped_ptr) doesn't require an in-depth understanding of rvalue references. 

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev

Jeremy Roman

unread,
Sep 24, 2014, 6:04:04 PM9/24/14
to hend...@chromium.org, Chromium-dev
If we allow move constructors in some set of cases, we should probably
also allow move assignment operators in the same cases.

James Robinson

unread,
Sep 24, 2014, 6:12:16 PM9/24/14
to Nico Weber, Dana Jansens, chromium-dev
On Wed, Sep 24, 2014 at 2:57 PM, Nico Weber <tha...@chromium.org> wrote:
I feel pretty strongly that we shouldn't allow anything that has something to do with rvalue references for a while, since as far as I can tell they aren't understand by many folks.

Having said that, I think it makes sense to make an exception to this for a few classes in base (scoped_ptr, probably the bind stuff), where using the feature (here: being able to write "return nullptr;" in a function that returns a scoped_ptr) doesn't require an in-depth understanding of rvalue references. 

I agree.  It's pretty hard to take advantage of this stuff without std::move() as well, which being a library feature we can't depend on yet.  I have a patch to make scoped_refptr<> movable and can get some very nice speedups on certain microbenchmarks but only when using std::move() judiciously.

Maybe allow this on a case-by-case basis for now?

- James

Dana Jansens

unread,
Sep 24, 2014, 6:13:51 PM9/24/14
to James Robinson, Nico Weber, chromium-dev
In the case of scoped_ptr we have a well-known Pass() method. Could we not use that in place of std::move() until it exists?

Maybe allow this on a case-by-case basis for now?

I'd be happy with that. I'll adjust my proposal to be "Allow move only constructors/assignment for the scoped_ptr class".

Dana Jansens

unread,
Sep 24, 2014, 9:11:41 PM9/24/14
to James Robinson, Nico Weber, chromium-dev
In the event that this is approved, this is what nullptr support in scoped_ptr could look like by making use of a move-only constructor (modulo review). https://codereview.chromium.org/599313003

James Robinson

unread,
Sep 25, 2014, 2:49:49 AM9/25/14
to Dana Jansens, Nico Weber, chromium-dev
On Wed, Sep 24, 2014 at 6:10 PM, Dana Jansens <dan...@chromium.org> wrote:

In the event that this is approved, this is what nullptr support in scoped_ptr could look like by making use of a move-only constructor (modulo review). https://codereview.chromium.org/599313003

This specifically allows using nullptr instead of scoped_ptr<T>(), which would be a really nice cleanup.

My inclination is to allow this specific use in scoped_ptr<> and allow folks to request specific other instances of move-only constructors, but not provide blanket approval yet.  There are many caveats about support in our current set of toolchains:

1.) move-only types work in some standard containers on some toolchains (that use c++11 aware standard libraries) but not in others, so code will compile on some developer's boxes but not others
2.) move-only constructors can't be =default-ed on MSVS, although this syntax works on other platforms. This means code that is initially written or only tested on non-windows platforms will fail on windows
3.) =delete'ing a copy constructor on a type will not correctly disable the move constructor on MSVS but will on other platforms, producing another inconsistency
4.) lack of library support for std::move() and std::forward() means developers either have to avoid these, which makes many things awkward, or learn a homegrown version that we add to base:: or somewhere else only to later need to convert over to the standard version.

Given how difficult this feature is to use to begin with I'd rather wait until the toolchain situation is completely clear so that developers can learn the feature once as it is supposed to be instead of having to learn the feature with a bunch of odd restrictions on top.

- James

Dana Jansens

unread,
Sep 25, 2014, 6:10:27 PM9/25/14
to James Robinson, Nico Weber, chromium-dev
It seems that there has been some support for allowing move-only constructors in special cases, and no one has disagreed with allowing this use in scoped_ptr.

I'd like to send a patch to add this in the allowed list, but make it clear that it's only in special cases. Should I just move it into the allowed section and say this in the notes?

Dana Jansens

unread,
Sep 26, 2014, 4:18:12 PM9/26/14
to James Robinson, Nico Weber, chromium-dev
Based on the results of this thread, I've landed a change to move Rvalue references into the banned section, with a note to revisit later, and that exceptional cases may be granted. https://codereview.chromium.org/607773002/

Alex Clarke

unread,
Aug 4, 2015, 12:33:19 PM8/4/15
to dan...@chromium.org, James Robinson, Nico Weber, chromium-dev
It's been nearly a year since this was last discussed.  I'm under the impression STLPort has gone now, so presumably library support isn't a problem anymore.  But what about the MSVC issues James R mentioned? Does MSVC2015 fix those?

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev

To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.

Nico Weber

unread,
Aug 4, 2015, 1:48:10 PM8/4/15
to Alex Clarke, Dana Jansens, James Robinson, chromium-dev
On Tue, Aug 4, 2015 at 9:32 AM, Alex Clarke <alexc...@google.com> wrote:
It's been nearly a year since this was last discussed.  I'm under the impression STLPort has gone now, so presumably library support isn't a problem anymore.

STLPort still isn't gone completely, OS X still uses libstdc++ 4.2, and we're still using MSVC 2013. See http://chromium-cpp.appspot.com/ for the up-to-date list of what's allowed. Nothing has changed in this area.

Victor Khimenko

unread,
Aug 4, 2015, 2:54:55 PM8/4/15
to Nico Weber, Alex Clarke, Dana Jansens, James Robinson, chromium-dev
On Tue, Aug 4, 2015 at 8:47 PM, Nico Weber <tha...@chromium.org> wrote:
On Tue, Aug 4, 2015 at 9:32 AM, Alex Clarke <alexc...@google.com> wrote:
It's been nearly a year since this was last discussed.  I'm under the impression STLPort has gone now, so presumably library support isn't a problem anymore.

STLPort still isn't gone completely, OS X still uses libstdc++ 4.2,

That one looks pretty tough: older versions of MacOS don't offer anything else thus we are kind of stuck. Have anyone tried to extend RHEL approach down to libstdc++ 4.2?

For the ones who don't know: RedHat offers modern developer tools for RHEL - even for RHEL 6 which uses libstdc++ 4.4. For that to work they offer libstdc++ which picks important bits and pieces from shared libstdc++ library yet includes modern headers and stdc++_nonshared.a to facilitate full C++11 compliance. It should be possible to do the same for MacOS, but there we'll need to go and additional step to support not libstdc++4.4, but libstdc++4.2. I'm not a MacOS guy thus I probably couldn't do it myself but if anyone is interested they could find sources for RedHat's GCC here:
And patch which provides libstdc++_nonshared.a is here:

Nico Weber

unread,
Aug 4, 2015, 2:57:31 PM8/4/15
to Victor Khimenko, Alex Clarke, Dana Jansens, James Robinson, chromium-dev
On Tue, Aug 4, 2015 at 11:54 AM, Victor Khimenko <kh...@chromium.org> wrote:


On Tue, Aug 4, 2015 at 8:47 PM, Nico Weber <tha...@chromium.org> wrote:
On Tue, Aug 4, 2015 at 9:32 AM, Alex Clarke <alexc...@google.com> wrote:
It's been nearly a year since this was last discussed.  I'm under the impression STLPort has gone now, so presumably library support isn't a problem anymore.

STLPort still isn't gone completely, OS X still uses libstdc++ 4.2,

That one looks pretty tough: older versions of MacOS don't offer anything else thus we are kind of stuck. Have anyone tried to extend RHEL approach down to libstdc++ 4.2?

The plan is to bundle libc++ on OS X.

Bruce

unread,
Aug 5, 2015, 2:15:31 PM8/5/15
to Chromium-dev, kh...@chromium.org, alexc...@google.com, dan...@chromium.org, jam...@chromium.org
I made a simple MoveOnly move-constructor default test (see below) and I have verified that it compiles with VC++ 2015 but not with VC++ 2013. So that issue appears to be resolved. I'm not sure about the issue with deleting a copy constructor not deleting the move constructor.

Either way, we don't yet have a plan for when we will move to VC++ 2015, so this is not yet useful.

#include <vector>

class MoveOnly
{
MoveOnly() = delete;
MoveOnly(const MoveOnly&) = delete;
MoveOnly& operator=(const MoveOnly&) = delete;
MoveOnly(MoveOnly&&) = default;

std::vector<char> data_;
};

Reply all
Reply to author
Forward
0 new messages