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/types.hpp>
50 std::enable_if_t<std::is_base_of<T, U>::value>* =
nullptr>
55 template <
typename U,
typename Deleter,
56 std::enable_if_t<std::is_base_of<T, U>::value>* =
nullptr>
62 std::enable_if_t<std::is_base_of<T, U>::value>* =
nullptr>
77 T*
get()
const {
return ptr_; }
80 explicit operator bool()
const {
return ptr_; }
96 std::remove_reference_t<decltype(*std::declval<std::decay_t<T>>())>;
99 template <
typename T,
typename =
void>
100 struct has_clone_impl : std::false_type {};
102 template <
typename T>
103 struct has_clone_impl<T, std::
void_t<decltype(std::declval<T>().clone())>>
106 template <
typename T>
107 constexpr
bool is_cloneable()
109 return has_clone_impl<std::decay_t<T>>::value;
113 template <
typename T,
typename =
void>
114 struct has_clone_to_impl : std::false_type {};
116 template <
typename T>
117 struct has_clone_to_impl<T,
118 std::
void_t<decltype(std::declval<T>().clone(
119 std::declval<std::shared_ptr<const Executor>>()))>>
122 template <
typename T>
123 constexpr
bool has_clone_to()
125 return has_clone_to_impl<std::decay_t<T>>::value;
129 template <
typename T>
130 struct have_ownership_impl : std::false_type {};
132 template <
typename T,
typename Deleter>
133 struct have_ownership_impl<std::unique_ptr<T, Deleter>> : std::true_type {};
135 template <
typename T>
136 struct have_ownership_impl<std::shared_ptr<T>> : std::true_type {};
138 template <
typename T>
139 using have_ownership_s = have_ownership_impl<std::decay_t<T>>;
141 template <
typename T>
142 constexpr
bool have_ownership()
144 return have_ownership_s<T>::value;
148 template <
typename Po
inter>
150 std::unique_ptr<typename std::remove_cv<pointee<Pointer>>::type>;
153 template <
typename Po
inter>
154 using shared_type = std::shared_ptr<pointee<Pointer>>;
173 template <
typename OwningPo
inter>
174 inline detail::shared_type<OwningPointer>
share(OwningPointer&& p)
176 static_assert(detail::have_ownership<OwningPointer>(),
177 "OwningPointer does not have ownership of the object");
178 static_assert(std::is_rvalue_reference<decltype(p)>::value,
179 "p must be an rvalue for this function to work");
180 return detail::shared_type<OwningPointer>(std::move(p));
196 template <
typename OwningPo
inter>
197 inline typename std::remove_reference<OwningPointer>::type&&
give(
200 static_assert(detail::have_ownership<OwningPointer>(),
201 "OwningPointer does not have ownership of the object");
216 template <
typename Po
inter>
217 GKO_DEPRECATED(
"no longer necessary, just pass the object without lend")
218 inline typename std::enable_if<detail::have_ownership_s<Pointer>::value,
219 detail::pointee<Pointer>*>::type
235 template <
typename Po
inter>
236 GKO_DEPRECATED(
"no longer necessary, just pass the object without lend")
237 inline typename std::enable_if<!detail::have_ownership_s<Pointer>::value,
238 detail::pointee<Pointer>*>::type
256 template <
typename T,
typename U>
257 inline std::decay_t<T>*
as(U* obj)
259 if (
auto p =
dynamic_cast<std::decay_t<T>*
>(obj)) {
263 std::string{
"gko::as<"} +
264 name_demangling::get_type_name(
typeid(T)) +
">",
265 name_demangling::get_type_name(
typeid(*obj)));
282 template <
typename T,
typename U>
283 inline const std::decay_t<T>*
as(
const U* obj)
285 if (
auto p =
dynamic_cast<const std::decay_t<T>*
>(obj)) {
289 std::string{
"gko::as<"} +
290 name_demangling::get_type_name(
typeid(T)) +
">",
291 name_demangling::get_type_name(
typeid(*obj)));
307 template <
typename T,
typename U>
310 return as<T>(obj.
get());
326 template <
typename T,
typename U>
329 return as<T>(obj.
get());
345 template <
typename T,
typename U>
346 inline std::unique_ptr<std::decay_t<T>>
as(std::unique_ptr<U>&& obj)
348 if (
auto p =
dynamic_cast<std::decay_t<T>*
>(obj.get())) {
350 return std::unique_ptr<std::decay_t<T>>{p};
353 name_demangling::get_type_name(
typeid(*obj)));
369 template <
typename T,
typename U>
370 inline std::shared_ptr<std::decay_t<T>>
as(std::shared_ptr<U> obj)
372 auto ptr = std::dynamic_pointer_cast<std::decay_t<T>>(obj);
377 name_demangling::get_type_name(
typeid(*obj)));
395 template <
typename T,
typename U>
396 inline std::shared_ptr<const std::decay_t<T>>
as(std::shared_ptr<const U> obj)
398 auto ptr = std::dynamic_pointer_cast<
const std::decay_t<T>>(obj);
403 name_demangling::get_type_name(
typeid(*obj)));
422 template <
typename Pointer,
423 std::enable_if_t<detail::is_cloneable<detail::pointee<Pointer>>()>* =
425 inline detail::cloned_type<Pointer>
clone(
const Pointer& p)
427 return detail::cloned_type<Pointer>(
428 static_cast<typename std::remove_cv<detail::pointee<Pointer>
>::type*>(
429 p->clone().release()));
435 template <
typename Pointer,
436 std::enable_if_t<!detail::is_cloneable<detail::pointee<Pointer>>()>* =
438 inline detail::cloned_type<Pointer>
clone(
const Pointer& p)
440 using type =
typename std::remove_cv<detail::pointee<Pointer>>::type;
442 return detail::cloned_type<Pointer>(dynamic_cast<type*>(
443 as<Cloneable>(ptr_param<const type>(p).get())->
clone().release()));
462 template <
typename Pointer,
463 std::enable_if_t<detail::has_clone_to<detail::pointee<Pointer>>()>* =
465 inline detail::cloned_type<Pointer>
clone(std::shared_ptr<const Executor> exec,
468 return detail::cloned_type<Pointer>(
469 static_cast<typename std::remove_cv<detail::pointee<Pointer>
>::type*>(
470 p->clone(std::move(exec)).release()));
476 template <
typename Pointer,
477 std::enable_if_t<!detail::has_clone_to<detail::pointee<Pointer>>()>* =
479 inline detail::cloned_type<Pointer>
clone(std::shared_ptr<const Executor> exec,
482 using type =
typename std::remove_cv<detail::pointee<Pointer>>::type;
484 return detail::cloned_type<Pointer>(
485 dynamic_cast<type*>(as<Cloneable>(ptr_param<const type>(p).get())
486 ->
clone(std::move(exec))
496 template <
typename T>
510 template <
typename T>
522 #endif // GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_