FINAL CUT
fdata.h
1 /***********************************************************************
2 * fdata.h - A general-purpose data wrapper *
3 * *
4 * This file is part of the FINAL CUT widget toolkit *
5 * *
6 * Copyright 2020-2023 Markus Gans *
7 * *
8 * FINAL CUT is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as *
10 * published by the Free Software Foundation; either version 3 of *
11 * the License, or (at your option) any later version. *
12 * *
13 * FINAL CUT is distributed in the hope that it will be useful, but *
14 * WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this program. If not, see *
20 * <http://www.gnu.org/licenses/>. *
21 ***********************************************************************/
22 
23 /* Inheritance diagram
24  * ═══════════════════
25  *
26  * ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▏
27  * ▕ FDataAccess ▏
28  * ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▏
29  * ▲
30  * │
31  * ▕▔▔▔▔▔▔▔▏
32  * ▕ FData ▏
33  * ▕▁▁▁▁▁▁▁▏
34  */
35 
36 #ifndef FDATA_H
37 #define FDATA_H
38 
39 #if !defined (USE_FINAL_H) && !defined (COMPILE_FINAL_CUT)
40  #error "Only <final/final.h> can be included directly."
41 #endif
42 
43 #include <utility>
44 
45 #include "final/util/fstring.h"
46 
47 namespace finalcut
48 {
49 
50 template <typename T>
51 class FData; // Class forward declaration
52 
53 // non-member functions
54 //----------------------------------------------------------------------
55 namespace internal
56 {
57 
58 // Enumerations
59 enum class IsArray { No, Yes };
60 enum class IsFunction { No, Yes };
61 
62 // Define the clean condition
63 template <typename T
64  , IsArray is_array = std::is_array<T>::value
65  ? IsArray::Yes
66  : IsArray::No
67  , IsFunction is_function = std::is_function<T>::value
68  ? IsFunction::Yes
69  : IsFunction::No>
71 
72 //----------------------------------------------------------------------
73 template <typename T>
74 struct cleanCondition<T, IsArray::No, IsFunction::No>
75 {
76  // Leave the type untouched
77  using type = T;
78 };
79 
80 //----------------------------------------------------------------------
81 template <typename T>
82 struct cleanCondition<T, IsArray::Yes, IsFunction::No>
83 {
84  // Array to pointer
85  using type = std::remove_extent_t<T>*;
86 };
87 
88 //----------------------------------------------------------------------
89 template <typename T>
90 struct cleanCondition<T, IsArray::No, IsFunction::Yes>
91 {
92  // Add pointer to function
93  using type = std::add_pointer_t<T>;
94 };
95 
96 //----------------------------------------------------------------------
97 template<typename T>
98 using cleanCondition_t = typename cleanCondition<T>::type;
99 
100 } // namespace internal
101 
102 //----------------------------------------------------------------------
103 template <typename T>
105 {
106  private:
107  using remove_ref = std::remove_reference_t<T>;
108 
109  public:
110  // Similar to std::decay, but keeps const and volatile
111  using type = internal::cleanCondition_t<remove_ref>;
112 };
113 
114 //----------------------------------------------------------------------
115 template <typename T>
116 using clean_fdata_t = typename cleanFData<T>::type;
117 
118 //----------------------------------------------------------------------
119 template <typename T>
120 constexpr auto makeFData (T&& data) -> FData<clean_fdata_t<T>>*
121 {
122  return new FData<clean_fdata_t<T>>(std::forward<T>(data));
123 }
124 
125 
126 //----------------------------------------------------------------------
127 // class FDataAccess
128 //----------------------------------------------------------------------
129 
131 {
132  public:
133  // Constructor
134  FDataAccess() = default;
135 
136  // Destructor
137  virtual ~FDataAccess() noexcept;
138 
139  // Accessors
140  virtual auto getClassName() const -> FString
141  {
142  return "FDataAccess";
143  }
144 
145  template<typename T>
146  constexpr auto get() -> clean_fdata_t<T>&
147  {
148  return static_cast<FData<clean_fdata_t<T>>&>(*this).get();
149  }
150 
151  // Mutator
152  template <typename T
153  , typename V>
154  constexpr void set (V&& data)
155  {
156  static_cast<FData<T>&>(*this).set(std::forward<V>(data));
157  }
158 };
159 
160 
161 //----------------------------------------------------------------------
162 // class FData
163 //----------------------------------------------------------------------
164 
165 template <typename T>
166 class FData : public FDataAccess
167 {
168  public:
169  using T_nocv = std::remove_cv_t<T>;
170 
171  // Constructors
172  explicit FData (T& v) // constructor
173  : value_ref{v}
174  { }
175 
176  explicit FData (T&& v) // constructor
177  : value{std::move(v)}
178  , value_ref{value}
179  { }
180 
181  ~FData() noexcept override = default; // Destructor
182 
183  FData (const FData& d) // Copy constructor
184  : value{d.value}
185  , value_ref{d.isInitializedCopy() ? std::ref(value) : d.value_ref}
186  { }
187 
188  FData (FData&& d) noexcept // Move constructor
189  : value{std::move(d.value)}
190  , value_ref{d.isInitializedCopy() ? std::ref(value) : std::move(d.value_ref)}
191  { }
192 
193  // Overloaded operators
194  auto operator = (const FData& d) -> FData& // Copy assignment operator (=)
195  {
196  if ( &d != this )
197  {
198  value = d.value;
199 
200  if ( d.isInitializedCopy() )
201  value_ref = value;
202  else
203  value_ref = d.value_ref;
204  }
205 
206  return *this;
207  }
208 
209  auto operator = (FData&& d) noexcept -> FData& // Move assignment operator (=)
210  {
211  if ( &d != this )
212  {
213  value = std::move(d.value);
214 
215  if ( d.isInitializedCopy() )
216  value_ref = value;
217  else
218  value_ref = std::move(d.value_ref);
219  }
220 
221  return *this;
222  }
223 
224  constexpr auto operator () () const -> T
225  {
226  return value_ref;
227  }
228 
229  constexpr explicit operator T () const
230  {
231  return value_ref;
232  }
233 
234  constexpr auto operator << (const T& v) -> FData&
235  {
236  value_ref.get() = v;
237  return *this;
238  }
239 
240  // Accessors
241  auto getClassName() const -> FString override
242  {
243  return "FData";
244  }
245 
246  constexpr auto get() const -> T&
247  {
248  return value_ref;
249  }
250 
251  // Mutator
252  constexpr void set (const T& v)
253  {
254  value_ref.get() = v;
255  }
256 
257  // Inquiries
258  constexpr auto isInitializedCopy() const -> bool
259  {
260  const auto* v = reinterpret_cast<void*>(const_cast<T_nocv*>(&value));
261  const auto* r = reinterpret_cast<void*>(const_cast<T_nocv*>(&value_ref.get()));
262  return v == r;
263  }
264 
265  constexpr auto isInitializedReference() const -> bool
266  {
267  return ! isInitializedCopy();
268  }
269 
270  // Friend Non-member operator functions
271  constexpr friend auto operator << (std::ostream &os, const FData& data) -> std::ostream&
272  {
273  os << data.value_ref.get();
274  return os;
275  }
276 
277  private:
278  // Data members
279  T value{};
280  std::reference_wrapper<T> value_ref;
281 };
282 
283 } // namespace finalcut
284 
285 #endif // FDATA_H
Definition: fdata.h:130
Definition: fdata.h:104
Definition: class_template.cpp:25
Definition: fstring.h:79
Definition: fdata.h:51