#pragma once namespace phosphor { namespace inventory { namespace manager { namespace details { namespace holder { /** @struct Base * @brief Adapt from any type base class. * * Provides an un-templated base class for use with an adapt to any type * adapter to enable containers of mixed types. */ struct Base { Base() = default; virtual ~Base() = default; Base(const Base&) = delete; Base& operator=(const Base&) = delete; Base(Base&&) = default; Base& operator=(Base&&) = default; }; /** @struct Holder * @brief Adapt from any type. * * Adapts any type to enable containers of mixed types. * * @tparam T - The adapted type. */ template struct Holder : public Base { Holder() = delete; virtual ~Holder() = default; Holder(const Holder&) = delete; Holder & operator=(const Holder&) = delete; Holder(Holder&&) = default; Holder& operator=(Holder&&) = default; explicit Holder(T&& held) : _held(std::forward(held)) {} /** @brief Construct an adapter. * * @param[in] held - The object to be adapted. * * @returns - std::unique pointer to the adapted object. * * @tparam Ret - The type of the pointer to be returned. * @tparam Held - The type of the object to be adapted. */ template static auto make_unique(Held&& held) { return std::make_unique( std::forward(held)); } /** @brief Construct an adapter. * * @param[in] held - The object to be adapted. * * @returns - std::shared pointer to the adapted object. * * @tparam Ret - The type of the pointer to be returned. * @tparam Held - The type of the object to be adapted. */ template static auto make_shared(Held&& held) { return std::make_shared( std::forward(held)); } protected: T _held; }; /** @struct CallableBase * @brief Adapt any callable function object base class. * * Provides an un-templated base class for use with an adapt to any * callable function object type. * * @tparam Ret - The return type of the callable. * @tparam Args - The argument types of the callable. */ template struct CallableBase { CallableBase() = default; virtual ~CallableBase() = default; CallableBase(const CallableBase&) = delete; CallableBase& operator=(const CallableBase&) = delete; CallableBase(CallableBase&&) = default; CallableBase& operator=(CallableBase&&) = default; virtual Ret operator()(Args&&...args) const = 0; virtual Ret operator()(Args&&...args) { return const_cast(*this)( std::forward(args)...); } }; /** @struct CallableHolder * @brief Adapt from any callable type. * * Adapts any callable type. * * @tparam T - The type of the callable. * @tparam Ret - The return type of the callable. * @tparam Args - The argument types of the callable. */ template struct CallableHolder final : public CallableBase, public Holder { CallableHolder() = delete; ~CallableHolder() = default; CallableHolder(const CallableHolder&) = delete; CallableHolder & operator=(const CallableHolder&) = delete; CallableHolder(CallableHolder&&) = default; CallableHolder& operator=(CallableHolder&&) = default; explicit CallableHolder(T&& func) : Holder(std::forward(func)) {} virtual Ret operator()(Args&&...args) const override { return this->_held(std::forward(args)...); } virtual Ret operator()(Args&&...args) override { return this->_held(std::forward(args)...); } }; } // namespace holder } // namespace details } // namespace manager } // namespace inventory } // namespace phosphor // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4