Don't return a large-ish array on the stack
[openal-soft.git] / common / comptr.h
blobf2355d058d08a4a77232cde74f77633089dd86bf
1 #ifndef COMMON_COMPTR_H
2 #define COMMON_COMPTR_H
4 #include <cstddef>
5 #include <utility>
7 #include "opthelpers.h"
10 template<typename T>
11 class ComPtr {
12 T *mPtr{nullptr};
14 public:
15 ComPtr() noexcept = default;
16 ComPtr(const ComPtr &rhs) : mPtr{rhs.mPtr} { if(mPtr) mPtr->AddRef(); }
17 ComPtr(ComPtr&& rhs) noexcept : mPtr{rhs.mPtr} { rhs.mPtr = nullptr; }
18 ComPtr(std::nullptr_t) noexcept { }
19 explicit ComPtr(T *ptr) noexcept : mPtr{ptr} { }
20 ~ComPtr() { if(mPtr) mPtr->Release(); }
22 ComPtr& operator=(const ComPtr &rhs)
24 if(!rhs.mPtr)
26 if(mPtr)
27 mPtr->Release();
28 mPtr = nullptr;
30 else
32 rhs.mPtr->AddRef();
33 try {
34 if(mPtr)
35 mPtr->Release();
36 mPtr = rhs.mPtr;
38 catch(...) {
39 rhs.mPtr->Release();
40 throw;
43 return *this;
45 ComPtr& operator=(ComPtr&& rhs)
47 if(&rhs != this) [[likely]]
49 if(mPtr) mPtr->Release();
50 mPtr = std::exchange(rhs.mPtr, nullptr);
52 return *this;
55 explicit operator bool() const noexcept { return mPtr != nullptr; }
57 T& operator*() const noexcept { return *mPtr; }
58 T* operator->() const noexcept { return mPtr; }
59 T* get() const noexcept { return mPtr; }
60 T** getPtr() noexcept { return &mPtr; }
62 T* release() noexcept { return std::exchange(mPtr, nullptr); }
64 void swap(ComPtr &rhs) noexcept { std::swap(mPtr, rhs.mPtr); }
65 void swap(ComPtr&& rhs) noexcept { std::swap(mPtr, rhs.mPtr); }
68 #endif