5 #ifndef GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
6 #define GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
10 #include <type_traits>
13 #include <ginkgo/core/base/executor.hpp>
14 #include <ginkgo/core/base/utils.hpp>
15 #include <ginkgo/core/log/logger.hpp>
48 this->
template log<log::Logger::polymorphic_object_deleted>(exec_.get(),
66 std::shared_ptr<const Executor> exec)
const
68 this->
template log<log::Logger::polymorphic_object_create_started>(
70 auto created = this->create_default_impl(std::move(exec));
71 this->
template log<log::Logger::polymorphic_object_create_completed>(
72 exec_.get(),
this, created.get());
99 std::unique_ptr<PolymorphicObject>
clone(
100 std::shared_ptr<const Executor> exec)
const
103 new_op->copy_from(
this);
115 std::unique_ptr<PolymorphicObject>
clone()
const
117 return this->
clone(exec_);
133 this->
template log<log::Logger::polymorphic_object_copy_started>(
134 exec_.get(), other,
this);
135 auto copied = this->copy_from_impl(other);
136 this->
template log<log::Logger::polymorphic_object_copy_completed>(
137 exec_.get(), other,
this);
156 template <
typename Derived,
typename Deleter>
158 "This function will be removed in a future release, the replacement "
159 "will copy instead of move. If a move is intended, use move_from "
165 this->
template log<log::Logger::polymorphic_object_move_started>(
166 exec_.get(), other.get(),
this);
167 auto copied = this->copy_from_impl(std::move(other));
168 this->
template log<log::Logger::polymorphic_object_move_completed>(
169 exec_.get(), other.get(),
this);
180 template <
typename Derived,
typename Deleter>
182 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
184 copy_from(
const std::unique_ptr<Derived, Deleter>& other)
193 const std::shared_ptr<const PolymorphicObject>& other)
211 this->
template log<log::Logger::polymorphic_object_move_started>(
212 exec_.get(), other.
get(),
this);
213 auto moved = this->move_from_impl(other.
get());
214 this->
template log<log::Logger::polymorphic_object_move_completed>(
215 exec_.get(), other.
get(),
this);
251 : exec_{std::move(exec)}
255 explicit PolymorphicObject(
const PolymorphicObject& other)
268 virtual std::unique_ptr<PolymorphicObject> create_default_impl(
269 std::shared_ptr<const Executor> exec)
const = 0;
279 virtual PolymorphicObject* copy_from_impl(
280 const PolymorphicObject* other) = 0;
290 virtual PolymorphicObject* copy_from_impl(
291 std::unique_ptr<PolymorphicObject> other) = 0;
301 virtual PolymorphicObject* move_from_impl(PolymorphicObject* other) = 0;
311 virtual PolymorphicObject* move_from_impl(
312 std::unique_ptr<PolymorphicObject> other) = 0;
320 virtual PolymorphicObject* clear_impl() = 0;
323 std::shared_ptr<const Executor> exec_;
345 template <
typename AbstractObject,
typename PolymorphicBase = PolymorphicObject>
348 using PolymorphicBase::PolymorphicBase;
350 std::unique_ptr<AbstractObject> create_default(
351 std::shared_ptr<const Executor> exec)
const
353 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
354 this->PolymorphicBase::create_default(std::move(exec)).release())};
357 std::unique_ptr<AbstractObject> create_default()
const
359 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
360 this->PolymorphicBase::create_default().release())};
363 std::unique_ptr<AbstractObject>
clone(
364 std::shared_ptr<const Executor> exec)
const
366 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
367 this->PolymorphicBase::clone(std::move(exec)).release())};
370 std::unique_ptr<AbstractObject>
clone()
const
372 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
373 this->PolymorphicBase::clone().release())};
378 return static_cast<AbstractObject*>(
379 this->PolymorphicBase::copy_from(other));
382 template <
typename Derived>
384 "This function will be removed in a future release, the replacement "
385 "will copy instead of move. If a move in intended, use move_to "
388 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
389 AbstractObject>* copy_from(std::unique_ptr<Derived>&& other)
391 return static_cast<AbstractObject*>(
392 this->PolymorphicBase::copy_from(std::move(other)));
395 template <
typename Derived>
397 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
399 copy_from(
const std::unique_ptr<Derived>& other)
401 return copy_from(other.get());
404 AbstractObject* copy_from(
405 const std::shared_ptr<const PolymorphicObject>& other)
407 return copy_from(other.get());
412 return static_cast<AbstractObject*>(
413 this->PolymorphicBase::move_from(other.
get()));
416 AbstractObject* clear()
418 return static_cast<AbstractObject*>(this->PolymorphicBase::clear());
431 #define GKO_ENABLE_SELF(_type) \
432 _type* self() noexcept { return static_cast<_type*>(this); } \
434 const _type* self() const noexcept \
436 return static_cast<const _type*>(this); \
470 template <
typename ResultType>
473 using result_type = ResultType;
482 virtual void convert_to(result_type* result)
const = 0;
503 virtual void move_to(result_type* result) = 0;
512 template <
typename R,
typename T>
513 std::unique_ptr<R, std::function<void(R*)>> copy_and_convert_to_impl(
514 std::shared_ptr<const Executor> exec, T* obj)
516 auto obj_as_r = dynamic_cast<R*>(obj);
517 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
519 return {obj_as_r, [](R*) {}};
521 auto copy = R::create(exec);
522 as<ConvertibleTo<std::decay_t<R>>>(obj)->convert_to(copy);
523 return {copy.release(), std::default_delete<R>{}};
528 template <
typename R,
typename T>
529 std::shared_ptr<R> copy_and_convert_to_impl(
530 std::shared_ptr<const Executor> exec, std::shared_ptr<T> obj)
532 auto obj_as_r = std::dynamic_pointer_cast<R>(obj);
533 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
536 auto copy = R::create(exec);
537 as<ConvertibleTo<std::decay_t<R>>>(obj.get())->convert_to(copy);
538 return {std::move(copy)};
562 template <
typename R,
typename T>
564 std::shared_ptr<const Executor> exec, T* obj)
566 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
576 template <
typename R,
typename T>
578 std::shared_ptr<const Executor> exec,
const T* obj)
580 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
601 template <
typename R,
typename T>
603 std::shared_ptr<T> obj)
605 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
616 template <
typename R,
typename T>
618 std::shared_ptr<const Executor> exec, std::shared_ptr<const T> obj)
620 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
661 template <
typename ConcreteObject,
typename PolymorphicBase = PolymorphicObject>
668 std::unique_ptr<PolymorphicObject> create_default_impl(
669 std::shared_ptr<const Executor> exec)
const override
671 return std::unique_ptr<ConcreteObject>{
new ConcreteObject(exec)};
676 as<ConvertibleTo<ConcreteObject>>(other)->convert_to(
self());
681 std::unique_ptr<PolymorphicObject> other)
override
683 as<ConvertibleTo<ConcreteObject>>(other.get())->move_to(
self());
689 as<ConvertibleTo<ConcreteObject>>(other)->move_to(
self());
694 std::unique_ptr<PolymorphicObject> other)
override
696 as<ConvertibleTo<ConcreteObject>>(other.get())->move_to(
self());
702 *
self() = ConcreteObject{this->get_executor()};
707 GKO_ENABLE_SELF(ConcreteObject);
723 template <
typename ConcreteType,
typename ResultType = ConcreteType>
726 using result_type = ResultType;
735 GKO_ENABLE_SELF(ConcreteType);
747 template <
typename ConcreteType>
750 template <
typename... Args>
751 static std::unique_ptr<ConcreteType> create(Args&&... args)
753 return std::unique_ptr<ConcreteType>(
754 new ConcreteType(std::forward<Args>(args)...));
762 #endif // GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_