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