Ginkgo  Generated from pipelines/1556235455 branch based on develop. Ginkgo version 1.9.0
A numerical linear algebra library targeting many-core architectures
utils_helper.hpp
1 // SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
6 #define GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
7 
8 
9 #include <functional>
10 #include <memory>
11 #include <type_traits>
12 
13 #include <ginkgo/core/base/exception.hpp>
14 #include <ginkgo/core/base/name_demangling.hpp>
15 #include <ginkgo/core/base/types.hpp>
16 
17 
18 #ifndef NDEBUG
19 #include <cstdio>
20 #endif // NDEBUG
21 
22 
23 namespace gko {
24 
25 
26 class Executor;
27 
28 
40 template <typename T>
41 class ptr_param {
42 public:
44  ptr_param(T* ptr) : ptr_{ptr} {}
45 
47  template <typename U,
48  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
49  ptr_param(const std::shared_ptr<U>& ptr) : ptr_param{ptr.get()}
50  {}
51 
53  template <typename U, typename Deleter,
54  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
55  ptr_param(const std::unique_ptr<U, Deleter>& ptr) : ptr_param{ptr.get()}
56  {}
57 
59  template <typename U,
60  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
61  ptr_param(const ptr_param<U>& ptr) : ptr_param{ptr.get()}
62  {}
63 
64  ptr_param(const ptr_param&) = default;
65 
66  ptr_param(ptr_param&&) = default;
67 
69  T& operator*() const { return *ptr_; }
70 
72  T* operator->() const { return ptr_; }
73 
75  T* get() const { return ptr_; }
76 
78  explicit operator bool() const { return ptr_; }
79 
80  ptr_param& operator=(const ptr_param&) = delete;
81 
82  ptr_param& operator=(ptr_param&&) = delete;
83 
84 private:
85  T* ptr_;
86 };
87 
88 
89 namespace detail {
90 
91 
92 template <typename T>
93 using pointee =
94  std::remove_reference_t<decltype(*std::declval<std::decay_t<T>>())>;
95 
96 
97 template <typename T, typename = void>
98 struct is_cloneable_impl : std::false_type {};
99 
100 template <typename T>
101 struct is_cloneable_impl<T, std::void_t<decltype(std::declval<T>().clone())>>
102  : std::true_type {};
103 
104 template <typename T>
105 constexpr bool is_cloneable()
106 {
107  return is_cloneable_impl<std::decay_t<T>>::value;
108 }
109 
110 
111 template <typename T, typename = void>
112 struct is_cloneable_to_impl : std::false_type {};
113 
114 template <typename T>
115 struct is_cloneable_to_impl<
116  T, std::void_t<decltype(std::declval<T>().clone(
117  std::declval<std::shared_ptr<const Executor>>()))>>
118  : std::true_type {};
119 
120 template <typename T>
121 constexpr bool is_cloneable_to()
122 {
123  return is_cloneable_to_impl<std::decay_t<T>>::value;
124 }
125 
126 
127 template <typename T>
128 struct have_ownership_impl : std::false_type {};
129 
130 template <typename T, typename Deleter>
131 struct have_ownership_impl<std::unique_ptr<T, Deleter>> : std::true_type {};
132 
133 template <typename T>
134 struct have_ownership_impl<std::shared_ptr<T>> : std::true_type {};
135 
136 template <typename T>
137 using have_ownership_s = have_ownership_impl<std::decay_t<T>>;
138 
139 template <typename T>
140 constexpr bool have_ownership()
141 {
142  return have_ownership_s<T>::value;
143 }
144 
145 
146 template <typename Pointer>
147 using cloned_type =
148  std::unique_ptr<typename std::remove_cv<pointee<Pointer>>::type>;
149 
150 
151 template <typename Pointer>
152 using shared_type = std::shared_ptr<pointee<Pointer>>;
153 
154 
155 } // namespace detail
156 
157 
172 template <typename Pointer>
173 inline detail::cloned_type<Pointer> clone(const Pointer& p)
174 {
175  static_assert(detail::is_cloneable<detail::pointee<Pointer>>(),
176  "Object is not cloneable");
177  return detail::cloned_type<Pointer>(
178  static_cast<typename std::remove_cv<detail::pointee<Pointer>>::type*>(
179  p->clone().release()));
180 }
181 
182 
198 template <typename Pointer>
199 inline detail::cloned_type<Pointer> clone(std::shared_ptr<const Executor> exec,
200  const Pointer& p)
201 {
202  static_assert(detail::is_cloneable_to<detail::pointee<Pointer>>(),
203  "Object is not cloneable");
204  return detail::cloned_type<Pointer>(
205  static_cast<typename std::remove_cv<detail::pointee<Pointer>>::type*>(
206  p->clone(std::move(exec)).release()));
207 }
208 
209 
223 template <typename OwningPointer>
224 inline detail::shared_type<OwningPointer> share(OwningPointer&& p)
225 {
226  static_assert(detail::have_ownership<OwningPointer>(),
227  "OwningPointer does not have ownership of the object");
228  static_assert(std::is_rvalue_reference<decltype(p)>::value,
229  "p must be an rvalue for this function to work");
230  return detail::shared_type<OwningPointer>(std::move(p));
231 }
232 
233 
246 template <typename OwningPointer>
247 inline typename std::remove_reference<OwningPointer>::type&& give(
248  OwningPointer&& p)
249 {
250  static_assert(detail::have_ownership<OwningPointer>(),
251  "OwningPointer does not have ownership of the object");
252  return std::move(p);
253 }
254 
255 
266 template <typename Pointer>
267 GKO_DEPRECATED("no longer necessary, just pass the object without lend")
268 inline typename std::enable_if<detail::have_ownership_s<Pointer>::value,
269  detail::pointee<Pointer>*>::type
270  lend(const Pointer& p)
271 {
272  return p.get();
273 }
274 
285 template <typename Pointer>
286 GKO_DEPRECATED("no longer necessary, just pass the object without lend")
287 inline typename std::enable_if<!detail::have_ownership_s<Pointer>::value,
288  detail::pointee<Pointer>*>::type
289  lend(const Pointer& p)
290 {
291  return p;
292 }
293 
294 
306 template <typename T, typename U>
307 inline std::decay_t<T>* as(U* obj)
308 {
309  if (auto p = dynamic_cast<std::decay_t<T>*>(obj)) {
310  return p;
311  } else {
312  throw NotSupported(__FILE__, __LINE__,
313  std::string{"gko::as<"} +
314  name_demangling::get_type_name(typeid(T)) + ">",
315  name_demangling::get_type_name(typeid(*obj)));
316  }
317 }
318 
332 template <typename T, typename U>
333 inline const std::decay_t<T>* as(const U* obj)
334 {
335  if (auto p = dynamic_cast<const std::decay_t<T>*>(obj)) {
336  return p;
337  } else {
338  throw NotSupported(__FILE__, __LINE__,
339  std::string{"gko::as<"} +
340  name_demangling::get_type_name(typeid(T)) + ">",
341  name_demangling::get_type_name(typeid(*obj)));
342  }
343 }
344 
345 
357 template <typename T, typename U>
358 inline std::decay_t<T>* as(ptr_param<U> obj)
359 {
360  return as<T>(obj.get());
361 }
362 
376 template <typename T, typename U>
377 inline const std::decay_t<T>* as(ptr_param<const U> obj)
378 {
379  return as<T>(obj.get());
380 }
381 
382 
395 template <typename T, typename U>
396 inline std::unique_ptr<std::decay_t<T>> as(std::unique_ptr<U>&& obj)
397 {
398  if (auto p = dynamic_cast<std::decay_t<T>*>(obj.get())) {
399  obj.release();
400  return std::unique_ptr<std::decay_t<T>>{p};
401  } else {
402  throw NotSupported(__FILE__, __LINE__, __func__,
403  name_demangling::get_type_name(typeid(*obj)));
404  }
405 }
406 
407 
419 template <typename T, typename U>
420 inline std::shared_ptr<std::decay_t<T>> as(std::shared_ptr<U> obj)
421 {
422  auto ptr = std::dynamic_pointer_cast<std::decay_t<T>>(obj);
423  if (ptr) {
424  return ptr;
425  } else {
426  throw NotSupported(__FILE__, __LINE__, __func__,
427  name_demangling::get_type_name(typeid(*obj)));
428  }
429 }
430 
431 
445 template <typename T, typename U>
446 inline std::shared_ptr<const std::decay_t<T>> as(std::shared_ptr<const U> obj)
447 {
448  auto ptr = std::dynamic_pointer_cast<const std::decay_t<T>>(obj);
449  if (ptr) {
450  return ptr;
451  } else {
452  throw NotSupported(__FILE__, __LINE__, __func__,
453  name_demangling::get_type_name(typeid(*obj)));
454  }
455 }
456 
457 
464 template <typename T>
466 public:
467  using pointer = T*;
468 
474  void operator()(pointer) const noexcept {}
475 };
476 
477 // a specialization for arrays
478 template <typename T>
479 class null_deleter<T[]> {
480 public:
481  using pointer = T[];
482 
483  void operator()(pointer) const noexcept {}
484 };
485 
486 
487 } // namespace gko
488 
489 
490 #endif // GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
gko::ptr_param::ptr_param
ptr_param(const std::unique_ptr< U, Deleter > &ptr)
Initializes the ptr_param from a unique_ptr.
Definition: utils_helper.hpp:55
gko::give
std::remove_reference< OwningPointer >::type && give(OwningPointer &&p)
Marks that the object pointed to by p can be given to the callee.
Definition: utils_helper.hpp:247
gko::ptr_param::ptr_param
ptr_param(const ptr_param< U > &ptr)
Initializes the ptr_param from a ptr_param of a derived type.
Definition: utils_helper.hpp:61
gko::ptr_param::operator->
T * operator->() const
Definition: utils_helper.hpp:72
gko::null_deleter
This is a deleter that does not delete the object.
Definition: utils_helper.hpp:465
gko::ptr_param::operator*
T & operator*() const
Definition: utils_helper.hpp:69
gko::null_deleter::operator()
void operator()(pointer) const noexcept
Deletes the object.
Definition: utils_helper.hpp:474
gko::ptr_param::get
T * get() const
Definition: utils_helper.hpp:75
gko::ptr_param::ptr_param
ptr_param(const std::shared_ptr< U > &ptr)
Initializes the ptr_param from a shared_ptr.
Definition: utils_helper.hpp:49
gko::NotSupported
NotSupported is thrown in case it is not possible to perform the requested operation on the given obj...
Definition: exception.hpp:127
gko::clone
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition: utils_helper.hpp:173
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:20
gko::as
std::decay_t< T > * as(U *obj)
Performs polymorphic type conversion.
Definition: utils_helper.hpp:307
gko::ptr_param
This class is used for function parameters in the place of raw pointers.
Definition: utils_helper.hpp:41
gko::share
detail::shared_type< OwningPointer > share(OwningPointer &&p)
Marks the object pointed to by p as shared.
Definition: utils_helper.hpp:224
gko::lend
std::enable_if< detail::have_ownership_s< Pointer >::value, detail::pointee< Pointer > * >::type lend(const Pointer &p)
Returns a non-owning (plain) pointer to the object pointed to by p.
Definition: utils_helper.hpp:270
gko::xstd::void_t
typename detail::make_void< Ts... >::type void_t
Use the custom implementation, since the std::void_t used in is_matrix_type_builder seems to trigger ...
Definition: std_extensions.hpp:47
gko::ptr_param::ptr_param
ptr_param(T *ptr)
Initializes the ptr_param from a raw pointer.
Definition: utils_helper.hpp:44