Why does std::unique_ptr not have a const get method?

For the same reason a T*const when dereferenced is a T&, not a T const&.

Constness of pointer is distinct from pointness of pointed-to.

get is const, it does not modify the state of unique_ptr.

Its constness does not impact the constness of the contents.

There is the idea of smart pointers that propogate constness, but unique_ptr is not that beast.

std::experimental::propogate_const wraps a pointer-like object and makes const travel through it.

It, or something like it, may solve your problem.

Note that I find half the time when I try to have const propogate like this, I discover I was wrong. But this may not be the case here.

In general, the proper way to handle the guts of a T*const in a const manner is to pass a T const& (or the nullable variant T const*).


Smart pointers are pretending to be a raw pointer. If you have class member which is raw pointer and use it in const method that you can't update a pointer, but you can modify object which is pointed. Same behavior is desired for smart pointer. So std::unique_ptr::get is a const method, but doesn't force to return pointer to const object.

Note also that you can have a pointer to const object.

MyClass *pointerToObject
std::unique_ptr<MyClass> smartPointerToObject;

// but you can have also a case
const MyClass *pointerToConstObject
std::unique_ptr<const MyClass> smartPointerToConstObject;

In last case std::unique_ptr::get will return something you are expecting.


Based on comment below:

Just provide private methods:

InnerClass& GetField() { return *uniquePtrToInnerClass; }
const InnerClass& GetField() const { return *uniquePtrToInnerClass; }

And use it in your code and you will have const object of inner class in const method.


There's no point to giving read-only access to an object via its unique_ptr. You only pass unique_ptr around when you are transferring ownership, for access to the object without an ownership transfer, call up.get() and pass a const T* to the function that should only read (or if the pointer is never nullptr, it's also reasonable to evaluate *(up.get()) and pass a const T&).

As a bonus, this allows you to use that function with objects stored on the stack, embedded inside another object, or managed with a smart pointer other than unique_ptr.

There's a good discussion of all the unique_ptr parameter passing cases (in/out, const/non-const, etc) here:

  • How do I pass a unique_ptr argument to a constructor or a function?