5 #ifndef GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
6 #define GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
10 #include <type_traits>
12 #include <ginkgo/core/base/executor.hpp>
13 #include <ginkgo/core/base/utils.hpp>
14 #include <ginkgo/core/log/logger.hpp>
47 this->
template log<log::Logger::polymorphic_object_deleted>(exec_.get(),
65 std::shared_ptr<const Executor> exec)
const
67 this->
template log<log::Logger::polymorphic_object_create_started>(
69 auto created = this->create_default_impl(std::move(exec));
70 this->
template log<log::Logger::polymorphic_object_create_completed>(
71 exec_.get(),
this, created.get());
98 std::unique_ptr<PolymorphicObject>
clone(
99 std::shared_ptr<const Executor> exec)
const
102 new_op->copy_from(
this);
114 std::unique_ptr<PolymorphicObject>
clone()
const
116 return this->
clone(exec_);
132 this->
template log<log::Logger::polymorphic_object_copy_started>(
133 exec_.get(), other,
this);
134 auto copied = this->copy_from_impl(other);
135 this->
template log<log::Logger::polymorphic_object_copy_completed>(
136 exec_.get(), other,
this);
155 template <
typename Derived,
typename Deleter>
157 "This function will be removed in a future release, the replacement "
158 "will copy instead of move. If a move is intended, use move_from "
164 this->
template log<log::Logger::polymorphic_object_move_started>(
165 exec_.get(), other.get(),
this);
166 auto copied = this->copy_from_impl(std::move(other));
167 this->
template log<log::Logger::polymorphic_object_move_completed>(
168 exec_.get(), other.get(),
this);
179 template <
typename Derived,
typename Deleter>
181 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
183 copy_from(
const std::unique_ptr<Derived, Deleter>& other)
192 const std::shared_ptr<const PolymorphicObject>& other)
210 this->
template log<log::Logger::polymorphic_object_move_started>(
211 exec_.get(), other.
get(),
this);
212 auto moved = this->move_from_impl(other.
get());
213 this->
template log<log::Logger::polymorphic_object_move_completed>(
214 exec_.get(), other.
get(),
this);
250 : exec_{std::move(exec)}
254 explicit PolymorphicObject(
const PolymorphicObject& other)
267 virtual std::unique_ptr<PolymorphicObject> create_default_impl(
268 std::shared_ptr<const Executor> exec)
const = 0;
278 virtual PolymorphicObject* copy_from_impl(
279 const PolymorphicObject* other) = 0;
289 virtual PolymorphicObject* copy_from_impl(
290 std::unique_ptr<PolymorphicObject> other) = 0;
300 virtual PolymorphicObject* move_from_impl(PolymorphicObject* other) = 0;
310 virtual PolymorphicObject* move_from_impl(
311 std::unique_ptr<PolymorphicObject> other) = 0;
319 virtual PolymorphicObject* clear_impl() = 0;
322 std::shared_ptr<const Executor> exec_;
344 template <
typename AbstractObject,
typename PolymorphicBase = PolymorphicObject>
347 using PolymorphicBase::PolymorphicBase;
349 std::unique_ptr<AbstractObject> create_default(
350 std::shared_ptr<const Executor> exec)
const
352 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
353 this->PolymorphicBase::create_default(std::move(exec)).release())};
356 std::unique_ptr<AbstractObject> create_default()
const
358 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
359 this->PolymorphicBase::create_default().release())};
362 std::unique_ptr<AbstractObject>
clone(
363 std::shared_ptr<const Executor> exec)
const
365 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
366 this->PolymorphicBase::clone(std::move(exec)).release())};
369 std::unique_ptr<AbstractObject>
clone()
const
371 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
372 this->PolymorphicBase::clone().release())};
377 return static_cast<AbstractObject*>(
378 this->PolymorphicBase::copy_from(other));
381 template <
typename Derived>
383 "This function will be removed in a future release, the replacement "
384 "will copy instead of move. If a move in intended, use move_to "
387 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
388 AbstractObject>* copy_from(std::unique_ptr<Derived>&& other)
390 return static_cast<AbstractObject*>(
391 this->PolymorphicBase::copy_from(std::move(other)));
394 template <
typename Derived>
396 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
398 copy_from(
const std::unique_ptr<Derived>& other)
400 return copy_from(other.get());
403 AbstractObject* copy_from(
404 const std::shared_ptr<const PolymorphicObject>& other)
406 return copy_from(other.get());
411 return static_cast<AbstractObject*>(
412 this->PolymorphicBase::move_from(other.
get()));
415 AbstractObject* clear()
417 return static_cast<AbstractObject*>(this->PolymorphicBase::clear());
430 #define GKO_ENABLE_SELF(_type) \
431 _type* self() noexcept { return static_cast<_type*>(this); } \
433 const _type* self() const noexcept \
435 return static_cast<const _type*>(this); \
469 template <
typename ResultType>
472 using result_type = ResultType;
481 virtual void convert_to(result_type* result)
const = 0;
502 virtual void move_to(result_type* result) = 0;
511 template <
typename R,
typename T>
512 std::unique_ptr<R, std::function<void(R*)>> copy_and_convert_to_impl(
513 std::shared_ptr<const Executor> exec, T* obj)
515 auto obj_as_r = dynamic_cast<R*>(obj);
516 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
518 return {obj_as_r, [](R*) {}};
520 auto copy = R::create(exec);
521 as<ConvertibleTo<std::decay_t<R>>>(obj)->convert_to(copy);
522 return {copy.release(), std::default_delete<R>{}};
527 template <
typename R,
typename T>
528 std::shared_ptr<R> copy_and_convert_to_impl(
529 std::shared_ptr<const Executor> exec, std::shared_ptr<T> obj)
531 auto obj_as_r = std::dynamic_pointer_cast<R>(obj);
532 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
535 auto copy = R::create(exec);
536 as<ConvertibleTo<std::decay_t<R>>>(obj.get())->convert_to(copy);
537 return {std::move(copy)};
561 template <
typename R,
typename T>
563 std::shared_ptr<const Executor> exec, T* obj)
565 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
575 template <
typename R,
typename T>
577 std::shared_ptr<const Executor> exec,
const T* obj)
579 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
600 template <
typename R,
typename T>
602 std::shared_ptr<T> obj)
604 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
615 template <
typename R,
typename T>
617 std::shared_ptr<const Executor> exec, std::shared_ptr<const T> obj)
619 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
660 template <
typename ConcreteObject,
typename PolymorphicBase = PolymorphicObject>
667 std::unique_ptr<PolymorphicObject> create_default_impl(
668 std::shared_ptr<const Executor> exec)
const override
670 return std::unique_ptr<ConcreteObject>{
new ConcreteObject(exec)};
675 as<ConvertibleTo<ConcreteObject>>(other)->convert_to(
self());
680 std::unique_ptr<PolymorphicObject> other)
override
682 as<ConvertibleTo<ConcreteObject>>(other.get())->move_to(
self());
688 as<ConvertibleTo<ConcreteObject>>(other)->move_to(
self());
693 std::unique_ptr<PolymorphicObject> other)
override
695 as<ConvertibleTo<ConcreteObject>>(other.get())->move_to(
self());
701 *
self() = ConcreteObject{this->get_executor()};
706 GKO_ENABLE_SELF(ConcreteObject);
722 template <
typename ConcreteType,
typename ResultType = ConcreteType>
725 using result_type = ResultType;
734 GKO_ENABLE_SELF(ConcreteType);
746 template <
typename ConcreteType>
749 template <
typename... Args>
750 static std::unique_ptr<ConcreteType> create(Args&&... args)
752 return std::unique_ptr<ConcreteType>(
753 new ConcreteType(std::forward<Args>(args)...));
761 #endif // GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_