26

I've been trying to define a defaulted move constructor in a class with a boost::optional member variable.

#include <boost/optional.hpp>
#include <utility>
#include <vector>

struct bar {std::vector<int> vec;};

struct foo {
  foo() = default;
  foo(foo&&) = default;
  boost::optional<bar> hello;
};

int main() {
  foo a;
  foo b(std::move(a));
}

My compiler supports both move semantics and defaulted move constructors, but I cannot get this to work.

% clang++ foo.cc -std=c++11 -stdlib=libc++
foo.cc:15:7: error: call to deleted constructor of 'foo'
  foo b(std::move(a));
      ^ ~~~~~~~~~~~~
foo.cc:9:3: note: function has been explicitly marked deleted here
  foo(foo&&) = default;
  ^
1 error generated.

Is there a way to move a boost::optional without modifying Boost's source code? Or should I wait until Boost supports moving?

I had the same problem with boost::any in the past.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510

3 Answers3

24

Boost.Optional supports move construction only since Boost version 1.56. See the release notes.

Andrzej
  • 5,027
  • 27
  • 36
18

Looking at boost::optional source code, it doesn't define move constructors or move assignments. However, it does define copy constructor and assignment, which prevent the compiler from auto-generating move constructor and assignment for it.

See Move constructor — Q&A:

the compiler will implicitly generate move constructor as member-wise moves, unless you have explicitly defined a copy constructor or copy/move assignment or a destructor

As Luc Danton suggests there needs to be a cure for that. Let's try using swap to move boost::optional in the hope that creating an empty boost::optional is cheap and then we just swap the default-constructed boost::optional with the one from the r-value foo, e.g.:

foo(foo&& b) {
    hello.swap(b.hello);
}

And same for the move assignment.

sehe
  • 374,641
  • 47
  • 450
  • 633
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • That is a correct diagnostic, but you need a cure to make this answer complete! – Luc Danton May 28 '12 at 12:21
  • Hmm, that's unfortunate. I could write a wrapper class that supports moving by using `std::swap`, and implicit conversion to `boost::optional`. I hope this will be fixed in the/a next version of Boost. –  May 29 '12 at 14:47
3

It's not clear how high on the agenda C++11 feature support for boost::optional is.

I found a nice fellow on the Internet who gave me some of his own code under a boost license...which is still undergoing some tweaks. It's at a point where it works for me. Maybe it will help anyone looking at this question:

https://github.com/hostilefork/CopyMoveConstrainedOptional

There is also a larger group effort to define a std::optional which has been going on...but their reference implementation wasn't able to handle some of the cases I had:

http://kojot.sggw.waw.pl/~akrzemi1/optional/tr2.optional.proposal.html