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