Ginkgo  Generated from pipelines/1363093349 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/std_extensions.hpp>
16 #include <ginkgo/core/base/types.hpp>
17 
18 
19 #ifndef NDEBUG
20 #include <cstdio>
21 #endif // NDEBUG
22 
23 
24 namespace gko {
25 
26 
27 class Executor;
28 
29 
41 template <typename T>
42 class ptr_param {
43 public:
45  ptr_param(T* ptr) : ptr_{ptr} {}
46 
48  template <typename U,
49  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
50  ptr_param(const std::shared_ptr<U>& ptr) : ptr_param{ptr.get()}
51  {}
52 
54  template <typename U, typename Deleter,
55  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
56  ptr_param(const std::unique_ptr<U, Deleter>& ptr) : ptr_param{ptr.get()}
57  {}
58 
60  template <typename U,
61  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
62  ptr_param(const ptr_param<U>& ptr) : ptr_param{ptr.get()}
63  {}
64 
65  ptr_param(const ptr_param&) = default;
66 
67  ptr_param(ptr_param&&) = default;
68 
70  T& operator*() const { return *ptr_; }
71 
73  T* operator->() const { return ptr_; }
74 
76  T* get() const { return ptr_; }
77 
79  explicit operator bool() const { return ptr_; }
80 
81  ptr_param& operator=(const ptr_param&) = delete;
82 
83  ptr_param& operator=(ptr_param&&) = delete;
84 
85 private:
86  T* ptr_;
87 };
88 
89 
90 namespace detail {
91 
92 
93 template <typename T>
94 using pointee =
95  std::remove_reference_t<decltype(*std::declval<std::decay_t<T>>())>;
96 
97 
98 template <typename T, typename = void>
99 struct is_clonable_impl : std::false_type {};
100 
101 template <typename T>
102 struct is_clonable_impl<T, xstd::void_t<decltype(std::declval<T>().clone())>>
103  : std::true_type {};
104 
105 template <typename T>
106 constexpr bool is_clonable()
107 {
108  return is_clonable_impl<std::decay_t<T>>::value;
109 }
110 
111 
112 template <typename T, typename = void>
113 struct is_clonable_to_impl : std::false_type {};
114 
115 template <typename T>
116 struct is_clonable_to_impl<
117  T, xstd::void_t<decltype(std::declval<T>().clone(
118  std::declval<std::shared_ptr<const Executor>>()))>>
119  : std::true_type {};
120 
121 template <typename T>
122 constexpr bool is_clonable_to()
123 {
124  return is_clonable_to_impl<std::decay_t<T>>::value;
125 }
126 
127 
128 template <typename T>
129 struct have_ownership_impl : std::false_type {};
130 
131 template <typename T, typename Deleter>
132 struct have_ownership_impl<std::unique_ptr<T, Deleter>> : std::true_type {};
133 
134 template <typename T>
135 struct have_ownership_impl<std::shared_ptr<T>> : std::true_type {};
136 
137 template <typename T>
138 using have_ownership_s = have_ownership_impl<std::decay_t<T>>;
139 
140 template <typename T>
141 constexpr bool have_ownership()
142 {
143  return have_ownership_s<T>::value;
144 }
145 
146 
147 template <typename Pointer>
148 using cloned_type =
149  std::unique_ptr<typename std::remove_cv<pointee<Pointer>>::type>;
150 
151 
152 template <typename Pointer>
153 using shared_type = std::shared_ptr<pointee<Pointer>>;
154 
155 
156 } // namespace detail
157 
158 
173 template <typename Pointer>
174 inline detail::cloned_type<Pointer> clone(const Pointer& p)
175 {
176  static_assert(detail::is_clonable<detail::pointee<Pointer>>(),
177  "Object is not clonable");
178  return detail::cloned_type<Pointer>(
179  static_cast<typename std::remove_cv<detail::pointee<Pointer>>::type*>(
180  p->clone().release()));
181 }
182 
183 
199 template <typename Pointer>
200 inline detail::cloned_type<Pointer> clone(std::shared_ptr<const Executor> exec,
201  const Pointer& p)
202 {
203  static_assert(detail::is_clonable_to<detail::pointee<Pointer>>(),
204  "Object is not clonable");
205  return detail::cloned_type<Pointer>(
206  static_cast<typename std::remove_cv<detail::pointee<Pointer>>::type*>(
207  p->clone(std::move(exec)).release()));
208 }
209 
210 
224 template <typename OwningPointer>
225 inline detail::shared_type<OwningPointer> share(OwningPointer&& p)
226 {
227  static_assert(detail::have_ownership<OwningPointer>(),
228  "OwningPointer does not have ownership of the object");
229  static_assert(std::is_rvalue_reference<decltype(p)>::value,
230  "p must be an rvalue for this function to work");
231  return detail::shared_type<OwningPointer>(std::move(p));
232 }
233 
234 
247 template <typename OwningPointer>
248 inline typename std::remove_reference<OwningPointer>::type&& give(
249  OwningPointer&& p)
250 {
251  static_assert(detail::have_ownership<OwningPointer>(),
252  "OwningPointer does not have ownership of the object");
253  return std::move(p);
254 }
255 
256 
267 template <typename Pointer>
268 GKO_DEPRECATED("no longer necessary, just pass the object without lend")
269 inline typename std::enable_if<detail::have_ownership_s<Pointer>::value,
270  detail::pointee<Pointer>*>::type
271  lend(const Pointer& p)
272 {
273  return p.get();
274 }
275 
286 template <typename Pointer>
287 GKO_DEPRECATED("no longer necessary, just pass the object without lend")
288 inline typename std::enable_if<!detail::have_ownership_s<Pointer>::value,
289  detail::pointee<Pointer>*>::type
290  lend(const Pointer& p)
291 {
292  return p;
293 }
294 
295 
307 template <typename T, typename U>
308 inline std::decay_t<T>* as(U* obj)
309 {
310  if (auto p = dynamic_cast<std::decay_t<T>*>(obj)) {
311  return p;
312  } else {
313  throw NotSupported(__FILE__, __LINE__,
314  std::string{"gko::as<"} +
315  name_demangling::get_type_name(typeid(T)) + ">",
316  name_demangling::get_type_name(typeid(*obj)));
317  }
318 }
319 
333 template <typename T, typename U>
334 inline const std::decay_t<T>* as(const U* obj)
335 {
336  if (auto p = dynamic_cast<const std::decay_t<T>*>(obj)) {
337  return p;
338  } else {
339  throw NotSupported(__FILE__, __LINE__,
340  std::string{"gko::as<"} +
341  name_demangling::get_type_name(typeid(T)) + ">",
342  name_demangling::get_type_name(typeid(*obj)));
343  }
344 }
345 
346 
358 template <typename T, typename U>
359 inline std::decay_t<T>* as(ptr_param<U> obj)
360 {
361  return as<T>(obj.get());
362 }
363 
377 template <typename T, typename U>
378 inline const std::decay_t<T>* as(ptr_param<const U> obj)
379 {
380  return as<T>(obj.get());
381 }
382 
383 
396 template <typename T, typename U>
397 inline std::unique_ptr<std::decay_t<T>> as(std::unique_ptr<U>&& obj)
398 {
399  if (auto p = dynamic_cast<std::decay_t<T>*>(obj.get())) {
400  obj.release();
401  return std::unique_ptr<std::decay_t<T>>{p};
402  } else {
403  throw NotSupported(__FILE__, __LINE__, __func__,
404  name_demangling::get_type_name(typeid(*obj)));
405  }
406 }
407 
408 
420 template <typename T, typename U>
421 inline std::shared_ptr<std::decay_t<T>> as(std::shared_ptr<U> obj)
422 {
423  auto ptr = std::dynamic_pointer_cast<std::decay_t<T>>(obj);
424  if (ptr) {
425  return ptr;
426  } else {
427  throw NotSupported(__FILE__, __LINE__, __func__,
428  name_demangling::get_type_name(typeid(*obj)));
429  }
430 }
431 
432 
446 template <typename T, typename U>
447 inline std::shared_ptr<const std::decay_t<T>> as(std::shared_ptr<const U> obj)
448 {
449  auto ptr = std::dynamic_pointer_cast<const std::decay_t<T>>(obj);
450  if (ptr) {
451  return ptr;
452  } else {
453  throw NotSupported(__FILE__, __LINE__, __func__,
454  name_demangling::get_type_name(typeid(*obj)));
455  }
456 }
457 
458 
465 template <typename T>
467 public:
468  using pointer = T*;
469 
475  void operator()(pointer) const noexcept {}
476 };
477 
478 // a specialization for arrays
479 template <typename T>
480 class null_deleter<T[]> {
481 public:
482  using pointer = T[];
483 
484  void operator()(pointer) const noexcept {}
485 };
486 
487 
488 } // namespace gko
489 
490 
491 #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:56
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:248
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:62
gko::ptr_param::operator->
T * operator->() const
Definition: utils_helper.hpp:73
gko::null_deleter
This is a deleter that does not delete the object.
Definition: utils_helper.hpp:466
gko::ptr_param::operator*
T & operator*() const
Definition: utils_helper.hpp:70
gko::null_deleter::operator()
void operator()(pointer) const noexcept
Deletes the object.
Definition: utils_helper.hpp:475
gko::ptr_param::get
T * get() const
Definition: utils_helper.hpp:76
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:50
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:174
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:19
gko::as
std::decay_t< T > * as(U *obj)
Performs polymorphic type conversion.
Definition: utils_helper.hpp:308
gko::ptr_param
This class is used for function parameters in the place of raw pointers.
Definition: utils_helper.hpp:42
gko::share
detail::shared_type< OwningPointer > share(OwningPointer &&p)
Marks the object pointed to by p as shared.
Definition: utils_helper.hpp:225
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:271
gko::ptr_param::ptr_param
ptr_param(T *ptr)
Initializes the ptr_param from a raw pointer.
Definition: utils_helper.hpp:45