File indexing completed on 2025-01-18 09:54:46
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include <type_traits>
0011 #include <utility>
0012
0013 namespace celeritas
0014 {
0015 namespace detail
0016 {
0017
0018 template<class T>
0019 struct DefaultFinalize
0020 {
0021 void operator()(T&) const noexcept {}
0022 };
0023
0024 }
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 template<class T, class Finalizer = detail::DefaultFinalize<T>>
0038 class InitializedValue
0039 {
0040 private:
0041 static inline constexpr bool ne_finalize_
0042 = noexcept(std::declval<Finalizer>()(std::declval<T&>()));
0043
0044 public:
0045
0046
0047
0048
0049 InitializedValue() = default;
0050
0051 InitializedValue(T const& value) : value_(value) {}
0052
0053 InitializedValue(T const& value, Finalizer fin)
0054 : value_(value), fin_(std::move(fin))
0055 {
0056 }
0057
0058 InitializedValue(T&& value) : value_(std::move(value)) {}
0059
0060 InitializedValue(T&& value, Finalizer fin)
0061 : value_(std::move(value)), fin_(std::move(fin))
0062 {
0063 }
0064
0065
0066 InitializedValue(InitializedValue const&) noexcept(
0067 std::is_nothrow_copy_constructible_v<T>)
0068 = default;
0069
0070
0071 InitializedValue(InitializedValue&& other) noexcept(
0072 std::is_nothrow_move_constructible_v<T>)
0073 : value_(std::exchange(other.value_, {}))
0074 {
0075 }
0076
0077
0078
0079
0080
0081
0082 InitializedValue& operator=(InitializedValue const& other) noexcept(
0083 ne_finalize_ && std::is_nothrow_copy_assignable_v<T>)
0084 {
0085 fin_(value_);
0086 value_ = other.value_;
0087 fin_ = other.fin_;
0088 return *this;
0089 }
0090
0091
0092 InitializedValue& operator=(InitializedValue&& other) noexcept(
0093 ne_finalize_ && std::is_nothrow_move_assignable_v<T>)
0094 {
0095 fin_(value_);
0096 value_ = std::exchange(other.value_, {});
0097 fin_ = std::exchange(other.fin_, {});
0098 return *this;
0099 }
0100
0101
0102 InitializedValue&
0103 operator=(T const& value) noexcept(ne_finalize_
0104 && std::is_nothrow_copy_assignable_v<T>)
0105 {
0106 fin_(value_);
0107 value_ = value;
0108 return *this;
0109 }
0110
0111
0112 void swap(InitializedValue& other) noexcept
0113 {
0114 using std::swap;
0115 swap(other.value_, value_);
0116 swap(other.fin_, fin_);
0117 }
0118
0119
0120
0121
0122
0123
0124 operator T const&() const noexcept { return value_; }
0125 operator T&() noexcept { return value_; }
0126
0127
0128 T const& value() const& { return value_; }
0129 T& value() & { return value_; }
0130 T&& value() && { return value_; }
0131
0132
0133
0134
0135
0136 Finalizer const& finalizer() const { return fin_; }
0137 void finalizer(Finalizer fin) { fin_ = std::move(fin); }
0138
0139
0140 private:
0141 T value_{};
0142 Finalizer fin_{};
0143 };
0144
0145
0146 }