user997112
user997112

Reputation: 30675

unique_ptr and pointer by reference argument type

I have code where I am trying to pass the underlying pointer of a unique_ptr in to a method accepting a pointer by reference:

unique_ptr<A> a;

func(a.get());

to call:

void func(A*& a){   // I am modifying what `a` points to in here

}

but I am getting compiler errors because get() is not returning what I expected was just the raw pointer. Is it possible to achieve what I am trying to do here?

Upvotes: 3

Views: 1066

Answers (3)

liquid
liquid

Reputation: 31

Here is an idea:

template<typename T> struct raw_from_ptr {
    raw_from_ptr(T& pointer) : _pointer(pointer), _raw_pointer(null_ptr) {}
    ~raw_from_ptr() {
        if (_raw_pointer != null_ptr)
            _pointer.reset(_raw_pointer);
    }
    raw_from_ptr(pointer_wrapper&& _other) : _pointer(_other._pointer) {
        std::swap(_raw_pointer, _other._raw_pointer);
    }
    operator typename T::pointer*() && { return &_raw_pointer; }
    operator typename T::pointer&() && { return _raw_pointer; }

private:
    T& _pointer;
    typename T::pointer _raw_pointer;
};

template<typename T> raw_from_ptr<T> get_raw_from_ptr(T& _pointer) {
    return raw_from_ptr<T>(_pointer);
}

Usage:

unique_ptr<A> a;
func(get_raw_from_ptr(a));

Upvotes: 3

Galik
Galik

Reputation: 48665

A function that takes a pointer by reference is strongly hinting that it may reallocate/delete the pointer in question. That means it is asking for ownership responsibilities. The only safe way to call such a function is to release the pointer from the unique pointer and (possibly) reacquire it after the call.

// a currently manages (owns) the pointer 
std::unique_ptr<A> a;

// release ownership of internal raw pointer
auto raw = a.release();

// call function (possibly modifying raw)
func(raw);

// (re)claim ownership of whatever func() returns
a.reset(raw);

But that can still be problematic if (say) the unique_ptr has a special deleter and the function doesn't re-allocate the object accordingly. Also if the function deletes the pointer without setting it to nullptr you will have a problem.

Upvotes: 4

Sebastian Redl
Sebastian Redl

Reputation: 72215

No, and that's a good thing.

The problem is that get() returns an rvalue, not a reference to unique_ptr's internal pointer. Therefore you can't modify it. If you could, you would completely mess up unique_ptr's internal state.

Just pass a reference to the unique_ptr itself if you want to modify it.

Upvotes: 13

Related Questions