5 #ifndef GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
6 #define GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
11 #include <type_traits>
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>
49 std::enable_if_t<std::is_base_of<T, U>::value>* =
nullptr>
54 template <
typename U,
typename Deleter,
55 std::enable_if_t<std::is_base_of<T, U>::value>* =
nullptr>
61 std::enable_if_t<std::is_base_of<T, U>::value>* =
nullptr>
76 T*
get()
const {
return ptr_; }
79 explicit operator bool()
const {
return ptr_; }
95 std::remove_reference_t<decltype(*std::declval<std::decay_t<T>>())>;
98 template <
typename T,
typename =
void>
99 struct is_clonable_impl : std::false_type {};
101 template <
typename T>
102 struct is_clonable_impl<T, xstd::void_t<decltype(std::declval<T>().clone())>>
105 template <
typename T>
106 constexpr
bool is_clonable()
108 return is_clonable_impl<std::decay_t<T>>::value;
112 template <
typename T,
typename =
void>
113 struct is_clonable_to_impl : std::false_type {};
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>>()))>>
121 template <
typename T>
122 constexpr
bool is_clonable_to()
124 return is_clonable_to_impl<std::decay_t<T>>::value;
128 template <
typename T>
129 struct have_ownership_impl : std::false_type {};
131 template <
typename T,
typename Deleter>
132 struct have_ownership_impl<std::unique_ptr<T, Deleter>> : std::true_type {};
134 template <
typename T>
135 struct have_ownership_impl<std::shared_ptr<T>> : std::true_type {};
137 template <
typename T>
138 using have_ownership_s = have_ownership_impl<std::decay_t<T>>;
140 template <
typename T>
141 constexpr
bool have_ownership()
143 return have_ownership_s<T>::value;
147 template <
typename Po
inter>
149 std::unique_ptr<typename std::remove_cv<pointee<Pointer>>::type>;
152 template <
typename Po
inter>
153 using shared_type = std::shared_ptr<pointee<Pointer>>;
173 template <
typename Po
inter>
174 inline detail::cloned_type<Pointer>
clone(
const Pointer& p)
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()));
199 template <
typename Po
inter>
200 inline detail::cloned_type<Pointer>
clone(std::shared_ptr<const Executor> exec,
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()));
224 template <
typename OwningPo
inter>
225 inline detail::shared_type<OwningPointer>
share(OwningPointer&& p)
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));
247 template <
typename OwningPo
inter>
248 inline typename std::remove_reference<OwningPointer>::type&&
give(
251 static_assert(detail::have_ownership<OwningPointer>(),
252 "OwningPointer does not have ownership of the object");
267 template <
typename Po
inter>
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
286 template <
typename Po
inter>
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
307 template <
typename T,
typename U>
308 inline std::decay_t<T>*
as(U* obj)
310 if (
auto p =
dynamic_cast<std::decay_t<T>*
>(obj)) {
314 std::string{
"gko::as<"} +
315 name_demangling::get_type_name(
typeid(T)) +
">",
316 name_demangling::get_type_name(
typeid(*obj)));
333 template <
typename T,
typename U>
334 inline const std::decay_t<T>*
as(
const U* obj)
336 if (
auto p =
dynamic_cast<const std::decay_t<T>*
>(obj)) {
340 std::string{
"gko::as<"} +
341 name_demangling::get_type_name(
typeid(T)) +
">",
342 name_demangling::get_type_name(
typeid(*obj)));
358 template <
typename T,
typename U>
361 return as<T>(obj.
get());
377 template <
typename T,
typename U>
380 return as<T>(obj.
get());
396 template <
typename T,
typename U>
397 inline std::unique_ptr<std::decay_t<T>>
as(std::unique_ptr<U>&& obj)
399 if (
auto p =
dynamic_cast<std::decay_t<T>*
>(obj.get())) {
401 return std::unique_ptr<std::decay_t<T>>{p};
404 name_demangling::get_type_name(
typeid(*obj)));
420 template <
typename T,
typename U>
421 inline std::shared_ptr<std::decay_t<T>>
as(std::shared_ptr<U> obj)
423 auto ptr = std::dynamic_pointer_cast<std::decay_t<T>>(obj);
428 name_demangling::get_type_name(
typeid(*obj)));
446 template <
typename T,
typename U>
447 inline std::shared_ptr<const std::decay_t<T>>
as(std::shared_ptr<const U> obj)
449 auto ptr = std::dynamic_pointer_cast<
const std::decay_t<T>>(obj);
454 name_demangling::get_type_name(
typeid(*obj)));
465 template <
typename T>
479 template <
typename T>
491 #endif // GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_