Ginkgo Generated from branch based on main. Ginkgo version 1.9.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#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
23namespace gko {
24
25
26class Executor;
27
28
40template <typename T>
41class ptr_param {
42public:
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
84private:
85 T* ptr_;
86};
87
88
89namespace detail {
90
91
92template <typename T>
93using pointee =
94 std::remove_reference_t<decltype(*std::declval<std::decay_t<T>>())>;
95
96
97template <typename T, typename = void>
98struct is_cloneable_impl : std::false_type {};
99
100template <typename T>
101struct is_cloneable_impl<T, std::void_t<decltype(std::declval<T>().clone())>>
102 : std::true_type {};
103
104template <typename T>
105constexpr bool is_cloneable()
106{
107 return is_cloneable_impl<std::decay_t<T>>::value;
108}
109
110
111template <typename T, typename = void>
112struct is_cloneable_to_impl : std::false_type {};
113
114template <typename T>
115struct 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
120template <typename T>
121constexpr bool is_cloneable_to()
122{
123 return is_cloneable_to_impl<std::decay_t<T>>::value;
124}
125
126
127template <typename T>
128struct have_ownership_impl : std::false_type {};
129
130template <typename T, typename Deleter>
131struct have_ownership_impl<std::unique_ptr<T, Deleter>> : std::true_type {};
132
133template <typename T>
134struct have_ownership_impl<std::shared_ptr<T>> : std::true_type {};
135
136template <typename T>
137using have_ownership_s = have_ownership_impl<std::decay_t<T>>;
138
139template <typename T>
140constexpr bool have_ownership()
141{
142 return have_ownership_s<T>::value;
143}
144
145
146template <typename Pointer>
147using cloned_type =
148 std::unique_ptr<typename std::remove_cv<pointee<Pointer>>::type>;
149
150
151template <typename Pointer>
152using shared_type = std::shared_ptr<pointee<Pointer>>;
153
154
155} // namespace detail
156
157
172template <typename Pointer>
173inline 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
198template <typename Pointer>
199inline 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
223template <typename OwningPointer>
224inline 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
246template <typename OwningPointer>
247inline 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
266template <typename Pointer>
267GKO_DEPRECATED("no longer necessary, just pass the object without lend")
268inline 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
285template <typename Pointer>
286GKO_DEPRECATED("no longer necessary, just pass the object without lend")
287inline 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
306template <typename T, typename U>
307inline 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
332template <typename T, typename U>
333inline 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
357template <typename T, typename U>
358inline std::decay_t<T>* as(ptr_param<U> obj)
359{
360 return as<T>(obj.get());
361}
362
376template <typename T, typename U>
377inline const std::decay_t<T>* as(ptr_param<const U> obj)
378{
379 return as<T>(obj.get());
380}
381
382
395template <typename T, typename U>
396inline 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
419template <typename T, typename U>
420inline 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
445template <typename T, typename U>
446inline 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
464template <typename T>
466public:
467 using pointer = T*;
468
474 void operator()(pointer) const noexcept {}
475};
476
477// a specialization for arrays
478template <typename T>
479class null_deleter<T[]> {
480public:
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_
The first step in using the Ginkgo library consists of creating an executor.
Definition executor.hpp:615
NotSupported is thrown in case it is not possible to perform the requested operation on the given obj...
Definition exception.hpp:127
This is a deleter that does not delete the object.
Definition utils_helper.hpp:465
void operator()(pointer) const noexcept
Deletes the object.
Definition utils_helper.hpp:474
This class is used for function parameters in the place of raw pointers.
Definition utils_helper.hpp:41
T & operator*() const
Definition utils_helper.hpp:69
ptr_param(const std::unique_ptr< U, Deleter > &ptr)
Initializes the ptr_param from a unique_ptr.
Definition utils_helper.hpp:55
ptr_param(const std::shared_ptr< U > &ptr)
Initializes the ptr_param from a shared_ptr.
Definition utils_helper.hpp:49
ptr_param(T *ptr)
Initializes the ptr_param from a raw pointer.
Definition utils_helper.hpp:44
T * get() const
Definition utils_helper.hpp:75
T * operator->() const
Definition utils_helper.hpp:72
ptr_param(const ptr_param< U > &ptr)
Initializes the ptr_param from a ptr_param of a derived type.
Definition utils_helper.hpp:61
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
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:270
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition utils_helper.hpp:173
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
std::decay_t< T > * as(U *obj)
Performs polymorphic type conversion.
Definition utils_helper.hpp:307
detail::shared_type< OwningPointer > share(OwningPointer &&p)
Marks the object pointed to by p as shared.
Definition utils_helper.hpp:224
STL namespace.