5 #ifndef GKO_PUBLIC_CORE_BASE_TEMPORARY_CONVERSION_HPP_
6 #define GKO_PUBLIC_CORE_BASE_TEMPORARY_CONVERSION_HPP_
11 #include <type_traits>
13 #include <ginkgo/core/base/lin_op.hpp>
14 #include <ginkgo/core/base/utils.hpp>
39 template <
typename CopyType,
typename OrigType>
40 class convert_back_deleter {
42 using pointer = CopyType*;
43 using original_pointer = OrigType*;
51 convert_back_deleter(original_pointer original) : original_{original} {}
58 void operator()(pointer ptr)
const
60 ptr->convert_to(original_);
65 original_pointer original_;
70 template <
typename CopyType,
typename OrigType>
71 class convert_back_deleter<const CopyType, const OrigType> {
73 using pointer =
const CopyType*;
74 using original_pointer =
const OrigType*;
75 convert_back_deleter(original_pointer) {}
77 void operator()(pointer ptr)
const {
delete ptr; }
90 template <
typename TargetType>
91 struct conversion_target_helper {
99 template <
typename SourceType,
100 typename = std::enable_if_t<std::is_base_of<
101 ConvertibleTo<TargetType>, SourceType>::value>>
102 static std::unique_ptr<TargetType> create_empty(
const SourceType* source)
104 return TargetType::create(source->get_executor());
119 template <
typename... ConversionCandidates>
120 struct conversion_helper {
122 template <
typename TargetType,
typename MaybeConstLinOp>
123 static std::unique_ptr<TargetType, std::function<void(TargetType*)>>
124 convert(MaybeConstLinOp* obj)
126 return convert_impl<TargetType, MaybeConstLinOp,
127 ConversionCandidates...>(obj);
135 template <
typename TargetType,
typename MaybeConstLinOp,
136 typename FirstCandidate,
typename... TrailingCandidates>
137 static std::unique_ptr<TargetType, std::function<void(TargetType*)>>
138 convert_impl(MaybeConstLinOp* obj)
141 using candidate_type =
142 std::conditional_t<std::is_const<MaybeConstLinOp>::value,
143 const FirstCandidate, FirstCandidate>;
144 candidate_type* cast_obj{};
145 if ((cast_obj = dynamic_cast<candidate_type*>(obj))) {
148 auto converted = conversion_target_helper<
149 std::remove_cv_t<TargetType>>::create_empty(cast_obj);
150 cast_obj->convert_to(converted);
153 std::is_base_of<ConvertibleTo<std::remove_cv_t<TargetType>>,
154 FirstCandidate>::value,
155 "ConvertibleTo not implemented");
156 static_assert(std::is_base_of<ConvertibleTo<FirstCandidate>,
158 "ConvertibleTo not symmetric");
159 return {converted.release(),
160 convert_back_deleter<TargetType, candidate_type>{cast_obj}};
163 return conversion_helper<TrailingCandidates...>::template convert<
170 struct conversion_helper<> {
171 template <
typename T,
typename MaybeConstLinOp>
172 static std::unique_ptr<T, std::function<void(T*)>> convert(
173 MaybeConstLinOp* obj)
176 return {
nullptr, null_deleter<T>{}};
193 template <
typename T>
194 class temporary_conversion {
196 using value_type = T;
199 std::conditional_t<std::is_const<T>::value,
const LinOp, LinOp>;
207 template <
typename... ConversionCandidates>
208 static temporary_conversion create(ptr_param<lin_op_type> ptr)
211 if ((cast_ptr = dynamic_cast<T*>(ptr.get()))) {
212 return handle_type{cast_ptr, null_deleter<T>{}};
214 return conversion_helper<ConversionCandidates...>::template convert<
224 T* get()
const {
return handle_.get(); }
231 T* operator->()
const {
return handle_.get(); }
236 explicit operator bool() {
return static_cast<bool>(handle_); }
241 using handle_type = std::unique_ptr<T, std::function<void(T*)>>;
243 temporary_conversion(handle_type handle) : handle_{std::move(handle)} {}
253 #endif // GKO_PUBLIC_CORE_BASE_TEMPORARY_CONVERSION_HPP_