Prevent std::move on object? - c++

I'm trying to create a not-null unique_ptr.
template <typename T>
class unique_ref {
public:
template <class... Types>
unique_ref(Types&&... Args) { mPtr = std::make_unique<T, Types...>(std::forward<Types>(Args)...); }
T* release() && { return mPtr.release(); }
T* release() & = delete;
private:
std::unique_ptr<T> mPtr;
};
My goal is to allow release() only if the unique_ref is a temporary.
The problem is someone could use std::move() to "get around" this:
unique_ref<int> p;
int* p2 = std::move(p).release();
Is there a way to prevent it from being move'd?

There is no way of distinguishing prvalues (temporaries) from xvalues (result of std::move) as far as overload resolution is concerned.
And there is no way of preventing std::move from converting an lvalue to an xvalue.
release is not an operation that can be supported by a non-null-guarantee "unique pointer". And neither is move construction / assignment. As far as I can tell, the only way to make the guarantee is to make the pointer non-movable, and make the copy operation allocate a deep copy.

You're going to have to let the std::move case go. When a user invokes std::move, they are giving a strong signal that they know exactly what they are doing.
You can protect yourself though during debug time.
For example, I would consider starting the class definition a little like this:
#include <memory>
#include <cassert>
template <typename T>
class unique_ref {
public:
// a number of problems here, but that is a discussuion for another day
template <class... Types>
unique_ref(Types&&... Args)
: mPtr(std::make_unique<T>(std::forward<Types>(Args)...))
{ }
// unique_ref is implicitly move-only
// see check below
bool has_value() const {
return bool(mPtr);
}
// here I am implicitly propagating the container's constness to the
// inner reference yielded. You may not want to do that.
// note that all these accessors are marshalled through one static function
// template. This gives me control of behaviour in exactly one place.
// (DRY principles)
auto operator*() -> decltype(auto) {
return *get_ptr(this);
}
auto operator*() const -> decltype(auto) {
return *get_ptr(this);
}
auto operator->() -> decltype(auto) {
return get_ptr(this);
}
auto operator->() const -> decltype(auto) {
return get_ptr(this);
}
private:
using implementation_type = std::unique_ptr<T>;
implementation_type release() { return std::move(mPtr); }
// this function is deducing constness of the container and propagating it
// that may not be what you want.
template<class MaybeConst>
static auto get_ptr(MaybeConst* self) -> decltype(auto)
{
auto ptr = self->mPtr.get();
assert(ptr);
using self_type = std::remove_pointer_t<decltype(self)>;
if constexpr (std::is_const<self_type>())
return static_cast<T const*>(ptr);
else
return ptr;
}
private:
implementation_type mPtr;
};
struct foo
{
};
auto generate()->unique_ref<foo> {
return unique_ref<foo>();
}
void test()
{
auto rfoo1 = generate();
auto rfoo2 = generate();
// auto rfoo3 = rfoo1; not copyable
// we have to assume that a user knows what he's doing here
auto rfoo3 = std::move(rfoo1);
// but we can add a check
assert(!rfoo1.has_value());
auto& a = *rfoo3;
static_assert(!std::is_const<std::remove_reference_t<decltype(a)>>());
const auto rfoo4 = std::move(rfoo3);
auto& b = *rfoo4;
static_assert(std::is_const<std::remove_reference_t<decltype(b)>>());
}

Related

How to implement a SingletonFactory?

I need some kind of class to manage the lifetime of singleton objects. I tried adding a method like this to my classes
static const FixedOutlineRect2D &instance() {
static const FixedOutlineRect2D self{};
return self;
}
Which has the nice property of constructing the object the first time it's called, but then it's not destroyed until the program is terminated which is messing up the order of deletions.
So I was thinking I could have some kind of "singleton factory" that would tie the lifetimes of all the objects to the factory and then I can destroy the whole thing as needed.
Here's what I've got so far:
class SingletonFactory {
public:
template<class T>
const T &get() {
if(!_map.template contains(typeid(T))) {
_map.template emplace(typeid(T), new T);
}
return *static_cast<const T*>(_map.at(typeid(T)));
}
~SingletonFactory() {
for(const auto& p : _map) {
delete p.second;
}
}
private:
std::unordered_map<std::type_index, const void*> _map{};
};
Usage would be like:
const Rect& rect = factory.get<FixedOutlineRect2D>();
Which would either coinstruct a new instance if one doesn't yet exist or return an existing instance.
But what I can't figure out is how to delete the instances. I'm getting an error:
Cannot delete expression with pointer-to-'void' type 'const void *'
Which makes sense because it can't know how many bytes to free unless it knows the type.
Can I get the type back out of the key so that I can cast and delete it? Or is there a better way to do what I'm trying?
This compiles and runs now:
class SingletonFactory {
public:
template<typename T, typename... Args>
const T &get(Args &&... args) {
// std::decay_t should be used
auto &cache = getCache<T, std::decay_t<Args>...>();
// Creating tuple from the arguments
auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
// Search for object in the cache
auto it = cache.find(arguments);
if (it != cache.end()) {
// Found. Return.
return *it->second;
}
// Not found. Add to cache.
auto *object = new T(std::forward<Args>(args)...);
cache.emplace(std::make_pair(std::move(arguments), object));
return *object;
}
private:
template<class T, class...Args>
static std::map<std::tuple<Args...>, const T *> &getCache() {
static std::map<std::tuple<Args...>, const T *> cache; // only run once
return cache;
}
};
(stolen and slightly modified from C++ templates std::tuple to void* and back)
But I still don't know how to clear out the caches... if I leave them as std::shared_ptr as OP had them it doesn't help exactly, they're still destructed at the end of the program. How can I iterate over all the static caches? If I had a map of caches/maps I could do it, but I don't think I can.
delete pointer to void will not call constructor ~T. You should store deleter of T. For example
std::unordered_map<std::type_index, std::pair<void*, void(*)(void*)>> _map;
_map.emplace(typeid(T), std::make_pair(new T, [](void* p){ delete static_cast<T*>(p); }));
for (const auto& p : _map) {
p.second.second(p.second.first);
}
I suggest making template SingletonFactory::get() a static member, and a static SingletonFactory::clean() instead of the destructor.
class SingletonFactory {
public:
template<class T>
static const T &get() {
if(!_map.count(typeid(T))) {
_map.emplace(typeid(T), std::make_pair(new T, [](const void* p){ delete (T*)(p); }));
}
return *static_cast<const T*>(_map.at(typeid(T)).first);
}
static void clean() {
for(const auto& p : _map) {
p.second.second(p.second.first);
}
}
private:
static std::unordered_map<std::type_index, std::pair<const void*, void(*)(const void*)>> _map;
};
std::unordered_map<std::type_index, std::pair<const void*, void(*)(const void*)>> SingletonFactory::_map;

Is it possible to implement a DefaultIfNull function in C++?

Disclaimer: This is rather more out of curiosity than for a lack of other solutions!
Is it possible to implement a function in C++ that:
gets passed a pointer of type T
either returns a reference-like-thing to the object pointed to by T
or, if the pointer is null, returns a reference-like-thing to a default constructed T() that has some sane lifetime?
Our first try was:
template<typename T>
T& DefaultIfNullDangling(T* ptr) {
if (!ptr) {
return T(); // xxx warning C4172: returning address of local variable or temporary
} else {
return *ptr;
}
}
A second attempt was done like this:
template<typename T>
T& DefaultIfNull(T* ptr, T&& callSiteTemp = T()) {
if (!ptr) {
return callSiteTemp;
} else {
return *ptr;
}
}
This gets rid of the warning and somewhat extends the lifetime of the temporary, but it's still rather error prone, I think.
Background:
The whole thing was triggered by an access pattern that looked like this:
if (pThing) {
for (auto& subThing : pThing->subs1) {
// ...
if (subThing.pSubSub) {
for (auto& subSubThing : *(subThing.pSubSub)) {
// ...
}
}
}
}
that could be "simplified" to:
for (auto& subThing : DefaultIfNull(pThing).subs1) {
// ...
for (auto& subSubThing : DefaultIfNull(subThing.pSubSub)) {
// ...
}
}
Yes, but it's going to be ugly:
#include <stdio.h>
#include <variant>
template <class T>
struct Proxy {
private:
std::variant<T*, T> m_data = nullptr;
public:
Proxy(T* p) {
if (p)
m_data = p;
else
m_data = T{};
}
T* operator->() {
struct Visitor {
T* operator()(T* t) { return t; }
T* operator()(T& t) { return &t; }
};
return std::visit(Visitor{}, m_data);
}
};
struct Thing1 {
int pSubSub[3] = {};
auto begin() const { return pSubSub; }
auto end() const { return pSubSub + 3; }
};
struct Thing2 {
Thing1* subs1[3] = {};
auto begin() const { return subs1; }
auto end() const { return subs1 + 3; }
};
template <class T>
auto NullOrDefault(T* p) {
return Proxy<T>(p);
}
int main() {
Thing1 a{1, 2, 3}, b{4, 5, 6};
Thing2 c{&a, nullptr, &b};
auto pThing = &c;
for (auto& subThing : NullOrDefault(pThing)->subs1) {
for (auto& subSubThing : NullOrDefault(subThing)->pSubSub) {
printf("%d, ", subSubThing);
}
putchar('\n');
}
}
There isn't really a good, idiomatic C++ solution that would exactly match what you're asking for.
A language where "EmptyIfNull" would work well, is probably one that has either garbage collection, or reference counted objects. So, we can achieve something similar in C++ by using reference counted pointers:
// never returns null, even if argument was null
std::shared_pr<T>
EmptyIfNull(std::shared_pr<T> ptr) {
return ptr
? ptr
: std::make_shared<T>();
}
Alternatively, you could return a reference to an object with static storage duration. However, I would not return a mutable reference when using such technique, since one caller might modify the object to be non-empty which might be highly confusing to another caller:
const T&
EmptyIfNull(T* ptr) {
static T empty{};
return ptr
? *ptr
: empty;
}
Alternatively, you could still return a mutable reference, but document that not modifying the empty object is a requirement that the caller must obey. That would be brittle, but that's par for the course in C++.
As another alternative, I was writing a suggestion to use a type-erasing wrapper that is either a reference, or an object, but Ayxan Haqverdili has got it covered already. Tons of boilerplate though.
Some alternative designs that adjust the premise a bit more, to be suitable to C++:
Return an object:
T
EmptyIfNull(T* ptr) {
return ptr
? *ptr
: T{};
}
Let the caller provide the default:
T&
ValueOrDefault(T* ptr, T& default_) {
return ptr
? *ptr
: default_;
}
Treat a non-null argument as a pre-condition:
T&
JustIndirectThrough(T* ptr) {
assert(ptr); // note that there may be better alternatives to the standard assert
return *ptr;
}
Treat a null argument as an error case:
T&
JustIndirectThrough(T* ptr) {
if (!ptr) {
// note that there are alternative error handling mechanisms
throw std::invalid_argument(
"I can't deal with this :(");
}
return *ptr;
}
Background:
I don't think the function that you're asking for is very attractive for the background that you give. Currently, you do nothing if the pointer is null, while with this suggestion you would be doing something with an empty object. If you dislike the deeply nested block, you could use this alternative:
if (!pThing)
continue; // or return, depending on context
for (auto& subThing : pThing->subs1) {
if (!subThing.pSubSub)
continue;
for (auto& subSubThing : *subThing.pSubSub) {
// ...
}
}
Or, perhaps you could establish an invariant that you never store null in the range, in which case you never need to check for null.
Sadly, but no. There is really no way to fully achieve what you want. Your options are:
If passed pointer is nullptr, return a reference to static object. This would only be correct if you are returning a const reference, otherwise, you are exposing yourself to a huge can of worms;
Return an std::optional<std::ref> and return unset optional if pointer is nullptr. This doesn't really solve your problem, as you still have to check at the call site if the optional is set, and you might as well check for the pointer to be nullptr instead at the call site. Alternatively, you can use value_or to extract value from optional, which would be akin to next option in a different packaging;
Use your second attempt, but remove default argument. This will mandate call site to provide a default object - this makes code somewhat ugly
If you only want to skip over nullptrs easily, you could just use boost::filter_iterator.
Now, this does not return default value on null pointer occurence, but neither does OP's original code; instead it wraps the container and provides the API to silently skip it in the for loop.
I skipped all the boilerplate code for brevity, hopefully the snippet below illustrates the idea well.
#include <iostream>
#include <memory>
#include <vector>
#include <boost/iterator/filter_iterator.hpp>
struct NonNull
{
bool operator()(const auto& x) const { return x!=nullptr;}
};
class NonNullVectorOfVectorsRef
{
public:
NonNullVectorOfVectorsRef(std::vector<std::unique_ptr<std::vector<int>>>& target)
: mUnderlying(target)
{}
auto end() const
{
return boost::make_filter_iterator<NonNull>(NonNull(), mUnderlying.end(), mUnderlying.end());
}
auto begin() const
{
return boost::make_filter_iterator<NonNull>(NonNull(), mUnderlying.begin(), mUnderlying.end());
}
private:
std::vector<std::unique_ptr<std::vector<int>>>& mUnderlying;
};
int main(int, char*[])
{
auto vouter=std::vector<std::unique_ptr<std::vector<int>>> {};
vouter.push_back(std::make_unique<std::vector<int>>(std::vector<int>{1,2,3,4,5}));
vouter.push_back(nullptr);
vouter.push_back(std::make_unique<std::vector<int>>(std::vector<int>{42}));
auto nn = NonNullVectorOfVectorsRef(vouter);
for (auto&& i:nn) {
for (auto&& j:(*i)) std::cout << j << ' ';
std::cout << '\n';
}
return 0;
}
If you accept std::shared_ptr<T>, you could use them to achieve this in a rather save and portable way:
template<typename T>
std::shared_ptr<T> NullOrDefault(std::shared_ptr<T> value)
{
if(value != nullptr)
{
return value;
}
return std::make_shared<T>();
}
From the comments:
One solution would be to implement a proxy range type containing a
pointer. This type would provide the begin and end members which
either forward the call to the pointed container or provide an empty
range. The usage would be basically identical to using a NullOrEmpty
function, in the context of a range-based for loop. – François
Andrieux yesterday
This is basically similar to what Ayxan provided in another answer, though this one here does work with exactly the client side syntax shown in the OP by providing begin() and end():
template<typename T>
struct CollectionProxy {
T* ref_;
// Note if T is a const-type you need to remove the const for the optional, otherwise it can't be reinitialized:
std::optional<typename std::remove_const<T>::type> defObj;
explicit CollectionProxy(T* ptr)
: ref_(ptr)
{
if (!ref_) {
defObj = T();
ref_ = &defObj.value();
}
}
using beginT = decltype(ref_->begin());
using endT = decltype(ref_->end());
beginT begin() const {
return ref_->begin();
}
endT end() const {
return ref_->end();
}
};
template<typename T>
CollectionProxy<T> DefaultIfNull(T* ptr) {
return CollectionProxy<T>(ptr);
}
void fun(const std::vector<int>* vecPtr) {
for (auto elem : DefaultIfNull(vecPtr)) {
std::cout << elem;
}
}
Notes:
Allowing for T and T const seems a wee bit tricky.
The solution using a variant would generate a smaller proxy object size (I think).
This is certainly gonna be more expensive at runtime than the if+for in the OP, after all you have to at least construct an (empty) temporary
I think providing an empty range could be done cheaper here if all you need is begin() and end(), but if this should generalize to more than just calls to begin() and end(), you would need a real temporary object of T anyways.

Non-copying std::shared_ptr<boost::any>?

I store "instances of different types" with "shared ownership". That's what I currently do:
class Destructible {
public:
virtual ~Destructible() = default;
};
// UGLY
class MyType1 : public Destructible { ... };
class MyTypeN : public Destructible { ... };
class Storage {
std::vector<std::shared_ptr<Destructible>> objects_;
...
}
I'd love to switch to boost::any, removing all these conformances and gaining the ability to store instances of truly any type. Also I like boost::any interface and boost::any_cast.
But my types don't satisfy ValueType requirements, they are not copyable. What is the best (preferably existing) solution for this problem? Something like shared_any_ptr, which captures destructor at creation, has type erasure, reference counter and can do any_cast.
Edit: boost::any allows creation with move, but I'd prefer not to even move and use pointers.
Edit2: I also use make_shared extensively, so something make_shared_any_ptr would come in handy.
This isn't tricky with shared pointers. We can even avoid multiple allocations.
struct any_block {
any_block(any_block const&)=delete;
template<class T>
T* try_get() {
if (!info || !ptr) return nullptr;
if (std::type_index(typeid(T)) != std::type_index(*info)) return nullptr;
return static_cast<T*>(ptr);
}
template<class T>
T const* try_get() const {
if (!info || !ptr) return nullptr;
if (std::type_index(typeid(T)) != std::type_index(*info)) return nullptr;
return static_cast<T const*>(ptr);
}
~any_block() {
cleanup();
}
protected:
void cleanup(){
if (dtor) dtor(this);
dtor=0;
}
any_block() {}
std::type_info const* info = nullptr;
void* ptr = nullptr;
void(*dtor)(any_block*) = nullptr;
};
template<class T>
struct any_block_made:any_block {
std::aligned_storage_t<sizeof(T), alignof(T)> data;
any_block_made() {}
~any_block_made() {}
T* get_unsafe() {
return static_cast<T*>((void*)&data);
}
template<class...Args>
void emplace(Args&&...args) {
ptr = ::new((void*)get_unsafe()) T(std::forward<Args>(args)...);
info = &typeid(T);
dtor = [](any_block* self){
static_cast<any_block_made<T>*>(self)->get_unsafe()->~T();
};
}
};
template<class D>
struct any_block_dtor:any_block {
std::aligned_storage_t<sizeof(D), alignof(D)> dtor_data;
any_block_dtor() {}
~any_block_dtor() {
cleanup();
if (info) dtor_unsafe()->~D();
}
D* dtor_unsafe() {
return static_cast<D*>((void*)&dtor_data);
}
template<class T, class D0>
void init(T* t, D0&& d) {
::new( (void*)dtor_unsafe() ) D(std::forward<D0>(d));
info = &typeid(T);
ptr = t;
dtor = [](any_block* s) {
auto* self = static_cast<any_block_dtor<D>*>(s);
(*self->dtor_unsafe())( static_cast<T*>(self->ptr) );
};
}
};
using any_ptr = std::shared_ptr<any_block>;
template<class T, class...Args>
any_ptr
make_any_ptr(Args&&...args) {
auto r = std::make_shared<any_block_made<T>>();
if (!r) return nullptr;
r->emplace(std::forward<Args>(args)...);
return r;
}
template<class T, class D=std::default_delete<T>>
any_ptr wrap_any_ptr( T* t, D&& d = {} ) {
auto r = std::make_shared<any_block_dtor<std::decay_t<D>>>();
if (!r) return nullptr;
r->init( t, std::forward<D>(d) );
return r;
}
you'd have to implement any_cast, but with try_get<T> it should be easy.
There may be some corner cases like const T that the above doesn't handle.
template<class T>
std::shared_ptr<T>
crystalize_any_ptr( any_ptr ptr ) {
if (!ptr) return nullptr;
T* pt = ptr->try_get<T>();
if (!pt) return nullptr;
return {pt, ptr}; // aliasing constructor
}
This lets you take a any_ptr and turn it into a shared_ptr<T> if the types match without copying anything.
live example.
You'll notice how similar any_block_made and any_block_dtor is. I believe that this is why at least one major shared_ptr in a std library reuses the spot the deleter lives in for make_shared itself.
I could probably do similar, and reduce binary size here. In addition, the T/D parameter of any_block_made and any_block_dtor is really just about how big and aligned the block of memory we play with is, and what exactly type erasued helper I store in the dtor pointer in the parent. A compiler/linker with COMDAT folding (MSVC or GOLD) may eliminate the binary bloat here, but with a bit of care I could do it myself.

How to have the compiler deduce the return type of a templated method in C++11?

I have a templated-method where the return-type is will be the result of a reinterpret_cast<>()-call.
class A {
void *_ptr;
public:
template<typename T>
T buffer() { return reinterpret_cast<T>(_ptr); }
};
This way makes me use the <>-syntax when calling this function:
A a;
auto b = a.buffer<double *>();
I'd prefer to call this method without the template arguments and let the compiler deduce the return type, based on the variable-type.
A a;
double *out = a.buffer();
Is this possible with return-type deduction?
I tried using auto, the->-operand and the trailing return type syntax.
auto buffer() -> decltype(reinterpret_cast<T>(_ptr)) const
{ return reinterpret_cast<T>(_ptr); }
but it still doesn't work.
Is there any way doing this, in C++11?
Yes, but only via a proxy type having a conversion function template:
struct BufferProxy {
void* ptr;
template<class T> operator T*() { return reinterpret_cast<T*>(ptr); }
};
BufferProxy buffer() { return BufferProxy{_ptr}; }
Example.
Note that users who have become familiar with the use of auto for return type deduction are likely to become confused by this technique:
auto out = a.buffer(); // out is BufferProxy
auto* out = a.buffer(); // fails to compile; can't deduce 'auto*' from 'a.A::buffer()'
Up until C++17, you can prevent auto out = a.buffer(); from compiling by giving BufferProxy a deleted copy constructor (and perhaps returning it by aggregate construction: return {_ptr};), but the user could still use auto&& and from C++17 guaranteed copy elision will make the auto form work again.
You may want a class something like the following. This would seem to offer most of what you want to do.
One issue I was wondering about was how to determine if a pointer stored into the class was the same type or not. So I thought it would be best to add an additional method to check the typeid() using the hash_code() method.
So the class I came up with using the operator idea of #ecatmur in his/her answer:
class A {
void *_ptr;
size_t _ptrHash;
public:
template<typename T> operator T*() { return reinterpret_cast<T *>(_ptr); }
template<typename T>
void SetPtr(T *p) { _ptr = p; _ptrHash = typeid(*p).hash_code(); }
template<typename T> bool operator == (T *p) { return p && typeid(*p).hash_code() == _ptrHash /* && p == _ptr */; }
};
The equality operator could either check only the type as above or if you uncomment the additional check, also check for value of the pointer. You probably just want to check for the type.
A simple demo function that I used to test this out was as follows:
void funky1() {
A a;
double ddd[50] = { 0.0 };
ddd[0] = 5.0; ddd[2] = 7.0;
a.SetPtr(&ddd[0]);
double *p = a;
bool bb = a == p;
long lll[50] = { 0 };
lll[0] = 5; lll[2] = 7;
long *q = a;
bb = a == q;
a.SetPtr(&lll[0]);
q = a;
bb = a == q;
}
I stepped through this with the debugger, Visual Studio 2013, and it looked like it worked like a champ.
I guess this answer is the most elegant.
Anyway, you can also let the class initializes your pointer as it follows:
class A {
void *_ptr;
public:
template<typename T>
void buffer(T **t) { *t = reinterpret_cast<T*>(_ptr); }
};
int main() {
A a;
double *b;
a.buffer(&b);
}
This way the type is deduced from the parameter list and you have not to explicitly specify it.

Atomic operations on `unique_ptr`

std::shared_ptr has specializations for atomic operations like atomic_compare_exchange_weak and family, but I cannot find documentation on equivalent specializations for std::unique_ptr. Are there any? If not, why not?
The reason that it is possible to provide an atomic instance of std::shared_ptr and it is not possible to do so for std::unique_ptr is hinted at in their signature. Compare:
std::shared_ptr<T> vs
std::unique_ptr<T, D> where D is the type of the Deleter.
std::shared_ptr needs to allocate a control-block where the strong and weak count are kept, so type-erasure of the deleter came at a trivial cost (a simply slightly larger control-block).
As a result, the layout of std::shared_ptr<T> is generally similar to:
template <typename T>
struct shared_ptr {
T* _M_ptr;
SomeCounterClass<T>* _M_counters;
};
And it is possible to atomically perform the exchange of those two pointers.
std::unique_ptr has a zero-overhead policy; using a std::unique_ptr should not incur any overhead compared to using a raw pointer.
As a result, the layout of std::unique_ptr<T, D> is generally similar to:
template <typename T, typename D = default_delete<T>>
struct unique_ptr {
tuple<T*, D> _M_t;
};
Where the tuple uses EBO (Empty Base Optimization) so that whenever D is zero-sized then sizeof(unique_ptr<T>) == sizeof(T*).
However, in the cases where D is NOT zero-sized, the implementation boils down to:
template <typename T, typename D = default_delete<T>>
struct unique_ptr {
T* _M_ptr;
D _M_del;
};
This D is the kicker here; it is not possible, in general, to guarantee that D can be exchange in an atomic fashion without relying on mutexes.
Therefore, it is not possible to provide an std::atomic_compare_exchange* suite of specialized routine for the generic std::unique_ptr<T, D>.
Note that the standard does not even guarantee that sizeof(unique_ptr<T>) == sizeof(T*) AFAIK, though it's a common optimization.
No there no standard atomic functions for std::unique_ptr.
I did find an argument for why not in Atomic Smart Pointers(N4058) by Herb Sutter
Lawrence Crowl responded to add:
One of the reasons that shared_ptr locking is the way it is is to avoid a situation in which we weaken the precondition on the atomic template parameter that it be trivial, and hence have no risk of deadlock.
That said, we could weaken the requirement so that the argument type only needs to be lockfree, or perhaps only non-recursively locking.
However, while trivial makes for reasonably testable traits, I see no effective mechanism to test for the weaker property.
That proposal has been assigned to the Concurrency Subgroup and has no disposition as of yet. You can check the status at JTC1/SC22/WG21 - Papers 2014 mailing2014-07
Be careful, sharing a modifiable unique_ptr between threads rarely makes sense, even if the pointer itself was atomic. If its contents changes, how can other threads know about it? They can't.
Consider this example:
unique_ptr<MyObject> p(new MyObject);
// Thread A
auto ptr = p.get();
if (ptr) {
ptr->do_something();
}
// Thread B
p.reset();
How can Thread A avoid using a dangling pointer after calling p.get()?
If you want to share an object between threads, use shared_ptr which has reference counting exactly for this purpose.
If you really wanted it, you can always roll your own atomic_unique_ptr, something along the lines (simplified):
#pragma once
#include <atomic>
#include <memory>
template<class T>
class atomic_unique_ptr
{
using pointer = T *;
std::atomic<pointer> ptr;
public:
constexpr atomic_unique_ptr() noexcept : ptr() {}
explicit atomic_unique_ptr(pointer p) noexcept : ptr(p) {}
atomic_unique_ptr(atomic_unique_ptr&& p) noexcept : ptr(p.release()) {}
atomic_unique_ptr& operator=(atomic_unique_ptr&& p) noexcept { reset(p.release()); return *this; }
atomic_unique_ptr(std::unique_ptr<T>&& p) noexcept : ptr(p.release()) {}
atomic_unique_ptr& operator=(std::unique_ptr<T>&& p) noexcept { reset(p.release()); return *this; }
void reset(pointer p = pointer()) { auto old = ptr.exchange(p); if (old) delete old; }
operator pointer() const { return ptr; }
pointer operator->() const { return ptr; }
pointer get() const { return ptr; }
explicit operator bool() const { return ptr != pointer(); }
pointer release() { return ptr.exchange(pointer()); }
~atomic_unique_ptr() { reset(); }
};
template<class T>
class atomic_unique_ptr<T[]> // for array types
{
using pointer = T *;
std::atomic<pointer> ptr;
public:
constexpr atomic_unique_ptr() noexcept : ptr() {}
explicit atomic_unique_ptr(pointer p) noexcept : ptr(p) {}
atomic_unique_ptr(atomic_unique_ptr&& p) noexcept : ptr(p.release()) {}
atomic_unique_ptr& operator=(atomic_unique_ptr&& p) noexcept { reset(p.release()); return *this; }
atomic_unique_ptr(std::unique_ptr<T>&& p) noexcept : ptr(p.release()) {}
atomic_unique_ptr& operator=(std::unique_ptr<T>&& p) noexcept { reset(p.release()); return *this; }
void reset(pointer p = pointer()) { auto old = ptr.exchange(p); if (old) delete[] old; }
operator pointer() const { return ptr; }
pointer operator->() const { return ptr; }
pointer get() const { return ptr; }
explicit operator bool() const { return ptr != pointer(); }
pointer release() { return ptr.exchange(pointer()); }
~atomic_unique_ptr() { reset(); }
};
NB: The code provided in this post is hereby released into Public Domain.