5 #ifndef GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
6 #define GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
11 #include <type_traits>
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>
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 is_clonable_impl : std::false_type {};
102 template <
typename T>
103 struct is_clonable_impl<T, xstd::void_t<decltype(std::declval<T>().clone())>>
106 template <
typename T>
107 constexpr
bool is_clonable()
109 return is_clonable_impl<std::decay_t<T>>::value;
113 template <
typename T,
typename =
void>
114 struct is_clonable_to_impl : std::false_type {};
116 template <
typename T>
117 struct is_clonable_to_impl<
118 T, xstd::void_t<decltype(std::declval<T>().clone(
119 std::declval<std::shared_ptr<const Executor>>()))>>
122 template <
typename T>
123 constexpr
bool is_clonable_to()
125 return is_clonable_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>>;
174 template <
typename Po
inter>
175 inline detail::cloned_type<Pointer>
clone(
const Pointer& p)
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()));
200 template <
typename Po
inter>
201 inline detail::cloned_type<Pointer>
clone(std::shared_ptr<const Executor> exec,
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()));
225 template <
typename OwningPo
inter>
226 inline detail::shared_type<OwningPointer>
share(OwningPointer&& p)
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));
248 template <
typename OwningPo
inter>
249 inline typename std::remove_reference<OwningPointer>::type&&
give(
252 static_assert(detail::have_ownership<OwningPointer>(),
253 "OwningPointer does not have ownership of the object");
268 template <
typename Po
inter>
269 GKO_DEPRECATED(
"no longer necessary, just pass the object without lend")
270 inline typename std::enable_if<detail::have_ownership_s<Pointer>::value,
271 detail::pointee<Pointer>*>::type
287 template <
typename Po
inter>
288 GKO_DEPRECATED(
"no longer necessary, just pass the object without lend")
289 inline typename std::enable_if<!detail::have_ownership_s<Pointer>::value,
290 detail::pointee<Pointer>*>::type
308 template <
typename T,
typename U>
309 inline std::decay_t<T>*
as(U* obj)
311 if (
auto p =
dynamic_cast<std::decay_t<T>*
>(obj)) {
315 std::string{
"gko::as<"} +
316 name_demangling::get_type_name(
typeid(T)) +
">",
317 name_demangling::get_type_name(
typeid(*obj)));
334 template <
typename T,
typename U>
335 inline const std::decay_t<T>*
as(
const U* obj)
337 if (
auto p =
dynamic_cast<const std::decay_t<T>*
>(obj)) {
341 std::string{
"gko::as<"} +
342 name_demangling::get_type_name(
typeid(T)) +
">",
343 name_demangling::get_type_name(
typeid(*obj)));
359 template <
typename T,
typename U>
362 return as<T>(obj.
get());
378 template <
typename T,
typename U>
381 return as<T>(obj.
get());
397 template <
typename T,
typename U>
398 inline std::unique_ptr<std::decay_t<T>>
as(std::unique_ptr<U>&& obj)
400 if (
auto p =
dynamic_cast<std::decay_t<T>*
>(obj.get())) {
402 return std::unique_ptr<std::decay_t<T>>{p};
405 name_demangling::get_type_name(
typeid(*obj)));
421 template <
typename T,
typename U>
422 inline std::shared_ptr<std::decay_t<T>>
as(std::shared_ptr<U> obj)
424 auto ptr = std::dynamic_pointer_cast<std::decay_t<T>>(obj);
429 name_demangling::get_type_name(
typeid(*obj)));
447 template <
typename T,
typename U>
448 inline std::shared_ptr<const std::decay_t<T>>
as(std::shared_ptr<const U> obj)
450 auto ptr = std::dynamic_pointer_cast<
const std::decay_t<T>>(obj);
455 name_demangling::get_type_name(
typeid(*obj)));
466 template <
typename T>
480 template <
typename T>
492 #endif // GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_