#ifndef SINGLETON_H #define SINGLETON_H #include "BoostLog.h" #include #include namespace Amass { using GlobalInstance = std::true_type; using LocalInstance = std::false_type; struct Construct {}; struct Reference {}; struct Register {}; template class Singleton; template class Singleton { public: template static std::shared_ptr instance(Args &&...args) { // LOG(debug) << typeid(T).name() << " address: " << (size_t)&m_instance; static_assert(std::is_base_of_v, "InstanceType must be child of T ..."); if constexpr (std::is_same_v) { if (!m_instance.expired()) { throw std::runtime_error("an instance have constructed ..."); } auto instance = std::shared_ptr(new InstanceType(std::forward(args)...)); m_instance = instance; return instance; } else if constexpr (std::is_same_v) { return m_instance.expired() ? nullptr : m_instance.lock(); } else if constexpr (std::is_same_v) { static_assert(sizeof...(args) == 1, "args must equal to 1..."); m_instance = std::get<0>(std::forward_as_tuple(args)...); return std::get<0>(std::forward_as_tuple(args)...); } else { static_assert(!std::is_same_v, "Can not to it!"); } } static std::weak_ptr weakPointer() { return m_instance; } private: Singleton() = delete; ~Singleton() = delete; Singleton(const Singleton &) = delete; Singleton &operator=(const Singleton &) = delete; private: inline static std::weak_ptr m_instance; }; template class Singleton { public: template static T *instance(Args &&...args) { if (!m_value) { m_value.reset(new T(std::forward(args)...)); } return m_value.get(); } private: Singleton() = delete; ~Singleton() = delete; Singleton(const Singleton &) = delete; Singleton &operator=(const Singleton &) = delete; private: inline static std::shared_ptr m_value; }; } // namespace Amass #endif // SINGLETON_H