How should I assign boost::interprocess::unique_ptr returned from a factory function, possibly using boost::move, in C++03

StackOverflow https://stackoverflow.com/questions/13086428

Question

I'm trying to create a factory function that would return boost::interprocess::unique_ptr. Here's an example:

#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
using namespace boost::interprocess;

class my_class {
public:
    my_class() {}
};

struct my_class_deleter {
    void operator()(my_class *p) {}
};

typedef unique_ptr<my_class, my_class_deleter> uptr;

uptr create() {
    return uptr();
}

int main() {
    uptr x;
    x = create();
    return 0;
}

The problem is that gcc fails to compile the above code saying:

main.cpp:22: error: ambiguous overload for ‘operator=’ in ‘x = create()()’
../../boost_latest/boost/interprocess/smart_ptr/unique_ptr.hpp:211: note: candidates are: boost::interprocess::unique_ptr<T, D>& boost::interprocess::unique_ptr<T, D>::operator=(boost::rv<boost::interprocess::unique_ptr<T, D> >&) [with T = my_class, D = my_class_deleter]
../../boost_latest/boost/interprocess/smart_ptr/unique_ptr.hpp:249: note:                 boost::interprocess::unique_ptr<T, D>& boost::interprocess::unique_ptr<T, D>::operator=(int boost::interprocess::unique_ptr<T, D>::nat::*) [with T = my_class, D = my_class_deleter]

When I change

x = create();

to

x = boost::move(create());

then gcc says:

main.cpp:22: error: invalid initialization of non-const reference of type ‘uptr&’ from a temporary of type ‘uptr’
../../boost_latest/boost/move/move.hpp:330: error: in passing argument 1 of ‘typename boost::move_detail::enable_if<boost::has_move_emulation_enabled<T>, boost::rv<T>&>::type boost::move(T&) [with T = uptr]’

Am I doing something wrong?

Interestingly, when I do:

uptr x2 = create();

the code compiles without any issues.

BTW: I use gcc v4.4.3 and Boost v1.51.0.


UPDATE:

I've been able to overcome this issue by using the following snippet:

x = static_cast<boost::rv<uptr>&>(create());

The above cast is based on the first version of ambiguous overload for operator= mentioned in the original question. The second one (operator=(int boost::interprocess::unique_ptr<T, D>::nat::*) is probably provided by the implementation to emulate std::unique_ptr::operator=(nullptr_t), which as a matter of fact resets the unique_ptr. It turns out, it also makes operator= ambiguous.

Unfortunately, using the above-mentioned static_cast<>() makes using my factory too much complicated.

One way to solve this problem would be to remove the second overload for operator=, as one can always explicitly call unique_ptr::reset().

Still, I'm wondering if and how boost::move() could help me with this issue.

Was it helpful?

Solution

This turned out to be a bug in the implementation of boost::interprocess:unique_ptr.

I reported it to the maintainer of the library (ticket #7598).

The bug has been fixed and the fix will be available in Boost v1.54.0.

OTHER TIPS

Not sure if it meets your use-case but rather than using unique_ptr, can't you make my_class a moveable type (with Boost::Move) and do things by value using Boost ValueFactory for the factory interface?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top