PrusaSlicer-NonPlainar/src/libslic3r/clonable_ptr.hpp

169 lines
4.6 KiB
C++
Raw Normal View History

// clonable_ptr: a smart pointer with a usage similar to unique_ptr, with the exception, that
// the copy constructor / copy assignment operator work by calling the ->clone() method.
// derived from https://github.com/SRombauts/shared_ptr/blob/master/include/unique_ptr.hpp
/**
* @file clonable_ptr.hpp
* @brief clonable_ptr is a fake implementation to use in place of a C++11 std::clonable_ptr when compiling on an older compiler.
*
* @see http://www.cplusplus.com/reference/memory/clonable_ptr/
*
* Copyright (c) 2014-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include "assert.h"
namespace Slic3r {
// Detect whether the compiler supports C++11 noexcept exception specifications.
#if defined(_MSC_VER) && _MSC_VER < 1900 && ! defined(noexcept)
#define noexcept throw()
#endif
template<class T>
class clonable_ptr
{
public:
/// The type of the managed object, aliased as member type
typedef T element_type;
/// @brief Default constructor
clonable_ptr() noexcept :
px(nullptr)
{
}
/// @brief Constructor with the provided pointer to manage
explicit clonable_ptr(T* p) noexcept :
px(p)
{
}
/// @brief Copy constructor, clones by calling the rhs.clone() method
clonable_ptr(const clonable_ptr& rhs) :
px(rhs ? rhs.px->clone() : nullptr)
{
}
/// @brief Move constructor, never throws
clonable_ptr(clonable_ptr&& rhs) noexcept :
px(rhs.px)
{
rhs.px = nullptr;
}
/// @brief Assignment operator
clonable_ptr& operator=(const clonable_ptr& rhs)
{
delete px;
px = rhs ? rhs.px->clone() : nullptr;
return *this;
}
/// @brief Move operator, never throws
clonable_ptr& operator=(clonable_ptr&& rhs)
{
delete px;
px = rhs.px;
rhs.px = nullptr;
return *this;
}
/// @brief the destructor releases its ownership and destroy the object
inline ~clonable_ptr() noexcept
{
destroy();
}
/// @brief this reset releases its ownership and destroy the object
inline void reset() noexcept
{
destroy();
}
/// @brief this reset release its ownership and re-acquire another one
void reset(T* p) noexcept
{
assert((nullptr == p) || (px != p)); // auto-reset not allowed
destroy();
px = p;
}
/// @brief Swap method for the copy-and-swap idiom (copy constructor and swap method)
void swap(clonable_ptr& rhs) noexcept
{
T *tmp = px;
px = rhs.px;
rhs.px = tmp;
}
/// @brief release the ownership of the px pointer without destroying the object!
inline void release() noexcept
{
px = nullptr;
}
// reference counter operations :
inline operator bool() const noexcept
{
return (nullptr != px); // TODO nullptrptr
}
// underlying pointer operations :
inline T& operator*() const noexcept
{
assert(nullptr != px);
return *px;
}
inline T* operator->() const noexcept
{
assert(nullptr != px);
return px;
}
inline T* get() const noexcept
{
// no assert, can return nullptr
return px;
}
private:
/// @brief release the ownership of the px pointer and destroy the object
inline void destroy() noexcept
{
delete px;
px = nullptr;
}
/// @brief hack: const-cast release the ownership of the px pointer without destroying the object!
inline void release() const noexcept
{
px = nullptr;
}
private:
T* px; //!< Native pointer
};
// comparison operators
template<class T, class U> inline bool operator==(const clonable_ptr<T>& l, const clonable_ptr<U>& r) noexcept
{
return (l.get() == r.get());
}
template<class T, class U> inline bool operator!=(const clonable_ptr<T>& l, const clonable_ptr<U>& r) noexcept
{
return (l.get() != r.get());
}
template<class T, class U> inline bool operator<=(const clonable_ptr<T>& l, const clonable_ptr<U>& r) noexcept
{
return (l.get() <= r.get());
}
template<class T, class U> inline bool operator<(const clonable_ptr<T>& l, const clonable_ptr<U>& r) noexcept
{
return (l.get() < r.get());
}
template<class T, class U> inline bool operator>=(const clonable_ptr<T>& l, const clonable_ptr<U>& r) noexcept
{
return (l.get() >= r.get());
}
template<class T, class U> inline bool operator>(const clonable_ptr<T>& l, const clonable_ptr<U>& r) noexcept
{
return (l.get() > r.get());
}
} // namespace Slic3r