File indexing completed on 2024-05-12 04:44:32
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 #ifndef CONSTPROPAGATINGUNIQUEPOINTER_H 0005 #define CONSTPROPAGATINGUNIQUEPOINTER_H 0006 0007 #include "importexport.h" 0008 #include <memory> 0009 0010 namespace PerceptualColor 0011 { 0012 /** @internal 0013 * 0014 * @brief A <tt>const</tt> propagating <tt>std::unique_ptr</tt> 0015 * 0016 * With normal <tt>std::unique_ptr</tt> pointers (and also with raw 0017 * C++ pointers), within <tt>const</tt> functions you can do non-const 0018 * operations <em>on objects that a pointer points to</em>. 0019 * 0020 * <em>This</em> pointer type is different: It propagates the constness of 0021 * the object members and propagates them to the call through the pointer; 0022 * it will trigger a compiler error if non-cost access to object members 0023 * or methods is done from within const functions. Apart from that, it 0024 * behaves like <tt>std::unique_ptr</tt>. 0025 * 0026 * Think of this template as a simple alternative to 0027 * <tt>std::experimental::propagate_const< std::unique_ptr<T> ></tt> 0028 * 0029 * Example code: 0030 * @snippet testconstpropagatinguniquepointer.cpp example 0031 * 0032 * Currently, move-assignment is not supported. Use 0033 * <tt>std::unique_prt::reset()</tt> instead. As there is no 0034 * support for deleters anyway, this should be equivalent. 0035 * 0036 * @note A @ref ConstPropagatingUniquePointer pointer variable itself 0037 * may not be const! @internal (Otherwise, this would make <tt>const</tt> 0038 * <em>all</em> access even to non-const functions of the pointed 0039 * object.) @endinternal 0040 * 0041 * @internal 0042 * 0043 * @sa @ref ConstPropagatingRawPointer 0044 * 0045 * This class inherits privately <tt>std::shared_ptr</tt> and not 0046 * <tt>std::unique_ptr</tt> because the latter will not compile on 0047 * the MSVC compiler when used with incomplete types, which is however 0048 * necessary for usage within @ref pimpl. 0049 * 0050 * @note This class could be replaced in the future by <tt> 0051 * <a href="https://en.cppreference.com/w/cpp/experimental/propagate_const"> 0052 * std::experimental::propagate_const</a></tt> if this one ever becomes 0053 * part of the C++ standard. (Experimental features however are optional 0054 * for compilers, so not all of them implement them. Furthermore, they 0055 * can still change. Therefore, we cannot use experimental features here.) 0056 * 0057 * @todo Would it be better to include (or link to) 0058 * https://github.com/jbcoe/propagate_const instead of having our own 0059 * implementation? Or remove propagate_const header from this library? */ 0060 // NOTE No PERCEPTUALCOLOR_IMPORTEXPORT for generic template definitions! 0061 template<typename T> 0062 class ConstPropagatingUniquePointer : private std::shared_ptr<T> 0063 { 0064 public: 0065 /** @brief Default constructor 0066 * 0067 * Creates a pointer that points to <tt>nullptr</tt>. */ 0068 explicit ConstPropagatingUniquePointer() 0069 : std::shared_ptr<T>(nullptr) 0070 { 0071 } 0072 0073 /** @brief Constructor 0074 * 0075 * @param pointerToObject Object to which to point */ 0076 explicit ConstPropagatingUniquePointer(T *pointerToObject) 0077 : std::shared_ptr<T>(pointerToObject) 0078 { 0079 } 0080 0081 /** @brief Default destructor 0082 * 0083 * This destructor is not marked as <tt>override</tt> because the 0084 * base class’s destructor is not virtual.*/ 0085 ~ConstPropagatingUniquePointer() noexcept = default; 0086 0087 // No copy/move assignment or constructor. 0088 ConstPropagatingUniquePointer(const ConstPropagatingUniquePointer &) = delete; 0089 ConstPropagatingUniquePointer(ConstPropagatingUniquePointer &&) = delete; 0090 ConstPropagatingUniquePointer &operator=(const ConstPropagatingUniquePointer &) = delete; // clazy:exclude=function-args-by-value 0091 ConstPropagatingUniquePointer &operator=(ConstPropagatingUniquePointer &&) = delete; 0092 0093 /** @brief Non-const pointer operator 0094 * 0095 * @returns Non-const pointer operator */ 0096 [[nodiscard]] T *operator->() 0097 { 0098 // cppcheck-suppress CastIntegerToAddressAtReturn // false positive 0099 return std::shared_ptr<T>::operator->(); 0100 } 0101 0102 /** @brief Const pointer operator 0103 * 0104 * @returns Const pointer */ 0105 [[nodiscard]] const T *operator->() const 0106 { 0107 // cppcheck-suppress CastIntegerToAddressAtReturn // false positive 0108 return std::shared_ptr<T>::operator->(); 0109 } 0110 0111 /** @brief Non-const dereference operator 0112 * 0113 * @returns Non-const dereference operator */ 0114 [[nodiscard]] T &operator*() 0115 { 0116 // cppcheck-suppress returnTempReference // false positive 0117 return std::shared_ptr<T>::operator*(); 0118 } 0119 0120 /** @brief Const dereference operator 0121 * 0122 * @returns Const dereference operator */ 0123 [[nodiscard]] const T &operator*() const 0124 { 0125 // cppcheck-suppress returnTempReference // false positive 0126 return std::shared_ptr<T>::operator*(); 0127 } 0128 0129 /** @brief Deletes the previously managed object (if any) and starts 0130 * to manage a new object. 0131 * 0132 * @param newObject The new object that will be managed. Can be 0133 * <tt>nullptr</tt> to not manage any object anymore. */ 0134 void reset(T *newObject = nullptr) 0135 { 0136 std::shared_ptr<T>::reset(newObject); 0137 } 0138 0139 /** @brief Swaps the managed objects. 0140 * 0141 * @param other Another @ref ConstPropagatingUniquePointer object to 0142 * swap the managed object with. */ 0143 void swap(ConstPropagatingUniquePointer &other) 0144 { 0145 std::shared_ptr<T>::swap(other); 0146 } 0147 0148 /** @brief Returns a pointer to the managed object or <tt>nullptr</tt> if 0149 * no object is owned. 0150 * 0151 * @returns A pointer to the managed object or <tt>nullptr</tt> if 0152 * no object is owned. */ 0153 [[nodiscard]] T *get() 0154 { 0155 // cppcheck-suppress CastIntegerToAddressAtReturn // false positive 0156 return std::shared_ptr<T>::get(); 0157 } 0158 }; 0159 0160 } // namespace PerceptualColor 0161 0162 #endif // CONSTPROPAGATINGUNIQUEPOINTER_H