5 #ifndef GKO_PUBLIC_CORE_BASE_TEMPORARY_CONVERSION_HPP_
6 #define GKO_PUBLIC_CORE_BASE_TEMPORARY_CONVERSION_HPP_
11 #include <type_traits>
14 #include <ginkgo/core/base/lin_op.hpp>
15 #include <ginkgo/core/base/utils.hpp>
40 template <
typename CopyType,
typename OrigType>
41 class convert_back_deleter {
43 using pointer = CopyType*;
44 using original_pointer = OrigType*;
52 convert_back_deleter(original_pointer original) : original_{original} {}
59 void operator()(pointer ptr)
const
61 ptr->convert_to(original_);
66 original_pointer original_;
71 template <
typename CopyType,
typename OrigType>
72 class convert_back_deleter<const CopyType, const OrigType> {
74 using pointer =
const CopyType*;
75 using original_pointer =
const OrigType*;
76 convert_back_deleter(original_pointer) {}
78 void operator()(pointer ptr)
const {
delete ptr; }
91 template <
typename TargetType>
92 struct conversion_target_helper {
100 template <
typename SourceType,
101 typename = std::enable_if_t<std::is_base_of<
102 ConvertibleTo<TargetType>, SourceType>::value>>
103 static std::unique_ptr<TargetType> create_empty(
const SourceType* source)
105 return TargetType::create(source->get_executor());
120 template <
typename... ConversionCandidates>
121 struct conversion_helper {
123 template <
typename TargetType,
typename MaybeConstLinOp>
124 static std::unique_ptr<TargetType, std::function<void(TargetType*)>>
125 convert(MaybeConstLinOp* obj)
127 return convert_impl<TargetType, MaybeConstLinOp,
128 ConversionCandidates...>(obj);
136 template <
typename TargetType,
typename MaybeConstLinOp,
137 typename FirstCandidate,
typename... TrailingCandidates>
138 static std::unique_ptr<TargetType, std::function<void(TargetType*)>>
139 convert_impl(MaybeConstLinOp* obj)
142 using candidate_type =
143 std::conditional_t<std::is_const<MaybeConstLinOp>::value,
144 const FirstCandidate, FirstCandidate>;
145 candidate_type* cast_obj{};
146 if ((cast_obj = dynamic_cast<candidate_type*>(obj))) {
149 auto converted = conversion_target_helper<
150 std::remove_cv_t<TargetType>>::create_empty(cast_obj);
151 cast_obj->convert_to(converted);
154 std::is_base_of<ConvertibleTo<std::remove_cv_t<TargetType>>,
155 FirstCandidate>::value,
156 "ConvertibleTo not implemented");
157 static_assert(std::is_base_of<ConvertibleTo<FirstCandidate>,
159 "ConvertibleTo not symmetric");
160 return {converted.release(),
161 convert_back_deleter<TargetType, candidate_type>{cast_obj}};
164 return conversion_helper<TrailingCandidates...>::template convert<
171 struct conversion_helper<> {
172 template <
typename T,
typename MaybeConstLinOp>
173 static std::unique_ptr<T, std::function<void(T*)>> convert(
174 MaybeConstLinOp* obj)
177 return {
nullptr, null_deleter<T>{}};
194 template <
typename T>
195 class temporary_conversion {
197 using value_type = T;
200 std::conditional_t<std::is_const<T>::value,
const LinOp, LinOp>;
208 template <
typename... ConversionCandidates>
209 static temporary_conversion create(ptr_param<lin_op_type> ptr)
212 if ((cast_ptr = dynamic_cast<T*>(ptr.get()))) {
213 return handle_type{cast_ptr, null_deleter<T>{}};
215 return conversion_helper<ConversionCandidates...>::template convert<
225 T* get()
const {
return handle_.get(); }
232 T* operator->()
const {
return handle_.get(); }
237 explicit operator bool() {
return static_cast<bool>(handle_); }
242 using handle_type = std::unique_ptr<T, std::function<void(T*)>>;
244 temporary_conversion(handle_type handle) : handle_{std::move(handle)} {}
254 #endif // GKO_PUBLIC_CORE_BASE_TEMPORARY_CONVERSION_HPP_