27

I am wondering why I get an error when compiling:

const std::unique_ptr<int> get() { 
    return std::make_unique<int>(10);
}

int main() { 

    const std::unique_ptr<int> value = get();

    return EXIT_SUCCESS;
}

I get the following error:

main.cpp: In function ‘int main()’:
main.cpp:10:44: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
     const std::unique_ptr<int> value = get();

It compiles correctly when I remove const from the get signature.

Is there any way to return a constant unique_ptr ?

7
  • 2
    Is the actual std::unique_ptr object supposed to be constant, or the data pointed to by it? Commented Jul 24, 2017 at 11:46
  • 1
    @MooingDuck As a return type, this is weird. Otherwise, pimpl comes to mind as a case where a const unique_ptr to a non-const object is sometimes used. In general there's nothing weird about const pointers to non-const. If it's wrong to make the pointer point elsewhere but right to mutate the pointed-to object through the pointer, a const pointer to non-const expresses and enforces that. If one follows the somewhat common practice of making most things const except when there's a reason not to, const pointers to non-const objects arise quite often. Commented Jul 24, 2017 at 19:02
  • 1
    @EliahKagan: A const pointer in pimpl makes moves/swaps slower than they need to be, but yes, in general there are cases where a const pointer makes sense. Commented Jul 24, 2017 at 20:34
  • 1
    This is an x/y question that I dunno why it got voted so high. You state that you want the unique_ptr to be constant, despite that const return values are weird enough even before a noncopyable type like unique_ptr is added into the mix, without explaining why you thought you wanted this oddity. I don't feel that 'why can I not do [weird thing without any apparent justification]' questions are useful, otherwise I could spend my whole day inventing and posting them. Commented Jul 24, 2017 at 21:45
  • 1
    @MooingDuck There seem to be plenty of cases where const pointers are a good idea, at least if one values const-correctness. Sure, if we have full control over the function signature, a reference should be used. However, a trivial example that comes to mind where a pointer is received is a stdlib algorithm like find_if over a range in a container holding pointers (reference_wrapper doesn't seem worth the hassle & should be const itself anyway!). If the possibility were left of accidentally mutating the pointer within the receiving function, & that happens, it's not going to end well. Commented Jul 24, 2017 at 21:51

1 Answer 1

55

Because the unique_ptr is constant it can not be moved only copied. And copying a unique_ptr is not allowed (otherwise it would not be "unique").

If the data pointed to by the pointer should be constant, then use std::unique_ptr<const int> instead.

Sign up to request clarification or add additional context in comments.

6 Comments

Just a quick note: OP's example has to compile in C++17 due to guaranteed copy elision.
@bogdan Are you sure? It doesn't compile for me on clang, gcc, or msvc with -std=c++17
@bogdan The std::unique_ptr copy-constructor and copy-assignment operators are marked as delete, which means it can't be used for any kind of copying, even if the copy can be elided.
@patatahooligan Could those be older versions of the compilers? It does compile for me using reasonably recent versions of all three, Clang 5, GCC 7.3, MSVC 15.9.
@Someprogrammerdude That's true and applies in this case for anything before C++17. The rules have changed in C++17 as a result of adopting P0135. Rationale and examples are in the R0 version of the paper. Basically, initializing from a prvalue of the same type as the destination is no longer seen as a copy/move from a temporary that can be elided; it explicitly creates the destination object based on the prvalue; there isn't anything to elide anymore.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.