/* * Copyright (c) Contributors to the Open 3D Engine Project * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #pragma once template class StaticInstanceSpecialization { }; // Specializations for std::vector and std::map which allows us to modify the // least amount of legacy code by mirroring the std APIs that are in use // These are not intended to be complete, just enough to shim existing legacy code template class StaticInstanceSpecialization> { public: using Container = std::vector; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using iterator = typename Container::iterator; using const_iterator = typename Container::const_iterator; using pointer = typename Container::pointer; using const_pointer = typename Container::const_pointer; using size_type = typename Container::size_type; template AZ_FORCE_INLINE typename AZStd::enable_if::value, reference>::type operator[](Integral index) { return get()[size_type(index)]; } template AZ_FORCE_INLINE typename AZStd::enable_if::value, const_reference>::type operator[](Integral index) const { return get()[size_type(index)]; } AZ_FORCE_INLINE iterator begin() { return get().begin(); } AZ_FORCE_INLINE const_iterator begin() const { return get().begin(); } AZ_FORCE_INLINE iterator end() { return get().end(); } AZ_FORCE_INLINE const_iterator end() const { return get().end(); } AZ_FORCE_INLINE iterator erase(iterator it) { return get().erase(it); } AZ_FORCE_INLINE iterator erase(iterator first, iterator last) { return get().erase(first, last); } AZ_FORCE_INLINE void resize(size_t size) { get().resize(size); } AZ_FORCE_INLINE void reserve(size_t size) { get().reserve(size); } AZ_FORCE_INLINE void clear() { get().clear(); } AZ_FORCE_INLINE size_type size() { return get().size(); } AZ_FORCE_INLINE void push_back(U&& val) { get().push_back(val); } AZ_FORCE_INLINE void push_back(const U& val) { get().push_back(val); } AZ_FORCE_INLINE bool empty() const { return get().empty(); } AZ_FORCE_INLINE iterator insert(U&& val) { return get().insert(val); } AZ_FORCE_INLINE iterator insert(iterator it, U&& val) { return get().insert(it, val); } AZ_FORCE_INLINE reference front() { return get().front(); } AZ_FORCE_INLINE const_reference front() const { return get().front(); } AZ_FORCE_INLINE reference back() { return get().back(); } AZ_FORCE_INLINE const_reference back() const { return get().back(); } AZ_FORCE_INLINE void pop_back() { get().pop_back(); } AZ_FORCE_INLINE pointer data() { return get().data(); } AZ_FORCE_INLINE const_pointer data() const { return get().data(); } void swap(Container& other) { get().swap(other); } private: Container& get() const; }; template class StaticInstanceSpecialization> { public: using Container = std::list; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using iterator = typename Container::iterator; using const_iterator = typename Container::const_iterator; using pointer = typename Container::pointer; using const_pointer = typename Container::const_pointer; using size_type = typename Container::size_type; AZ_FORCE_INLINE iterator begin() { return get().begin(); } AZ_FORCE_INLINE const_iterator begin() const { return get().begin(); } AZ_FORCE_INLINE iterator end() { return get().end(); } AZ_FORCE_INLINE const_iterator end() const { return get().end(); } AZ_FORCE_INLINE iterator erase(iterator it) { return get().erase(it); } AZ_FORCE_INLINE iterator erase(iterator first, iterator last) { return get().erase(first, last); } AZ_FORCE_INLINE void resize(size_t size) { get().resize(size); } AZ_FORCE_INLINE void reserve(size_t size) { get().reserve(size); } AZ_FORCE_INLINE void clear() { get().clear(); } AZ_FORCE_INLINE size_type size() { return get().size(); } AZ_FORCE_INLINE void push_back(U&& val) { get().push_back(val); } AZ_FORCE_INLINE void push_back(const U& val) { get().push_back(val); } AZ_FORCE_INLINE void push_front(U&& val) { get().push_front(val); } AZ_FORCE_INLINE void push_front(const U& val) { get().push_front(val); } AZ_FORCE_INLINE bool empty() const { return get().empty(); } AZ_FORCE_INLINE iterator insert(U&& val) { return get().insert(val); } AZ_FORCE_INLINE iterator insert(iterator it, U&& val) { return get().insert(it, val); } AZ_FORCE_INLINE reference front() { return get().front(); } AZ_FORCE_INLINE const_reference front() const { return get().front(); } AZ_FORCE_INLINE reference back() { return get().back(); } AZ_FORCE_INLINE const_reference back() const { return get().back(); } AZ_FORCE_INLINE void pop_back() { get().pop_back(); } AZ_FORCE_INLINE pointer data() { return get().data(); } AZ_FORCE_INLINE const_pointer data() const { return get().data(); } void swap(Container& other) { get().swap(other); } private: Container& get() const; }; template class StaticInstanceSpecialization> { public: using Container = std::map; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using iterator = typename Container::iterator; using const_iterator = typename Container::const_iterator; using key_type = typename Container::key_type; using mapped_type = typename Container::mapped_type; using value_type = typename Container::value_type; using size_type = typename Container::size_type; using pair_iter_bool = std::pair; AZ_FORCE_INLINE iterator begin() { return get().begin(); } AZ_FORCE_INLINE const_iterator begin() const { return get().begin(); } AZ_FORCE_INLINE iterator end() { return get().end(); } AZ_FORCE_INLINE const_iterator end() const { return get().end(); } AZ_FORCE_INLINE iterator erase(iterator it) { return get().erase(it); } AZ_FORCE_INLINE size_t erase(const key_type& key) { return get().erase(key); } AZ_FORCE_INLINE mapped_type& operator[](const key_type& key) { return get()[key]; } template AZ_FORCE_INLINE typename AZStd::enable_if::value, mapped_type&>::type operator[](const K2& keylike) { return get()[key_type(keylike)]; } AZ_FORCE_INLINE iterator find(const key_type& key) { return get().find(key); } AZ_FORCE_INLINE const_iterator find(const key_type& key) const { return get().find(key); } AZ_FORCE_INLINE void clear() { get().clear(); } AZ_FORCE_INLINE bool empty() const { return get().empty(); } AZ_FORCE_INLINE iterator insert(iterator hint, const value_type& kv) { return get().insert(hint, kv); } AZ_FORCE_INLINE pair_iter_bool insert(const value_type& kv) { return get().insert(kv); } AZ_FORCE_INLINE size_type size() const { return get().size(); } void swap(Container& cont) { get().swap(cont); } private: Container& get() const; }; template class StaticInstanceSpecialization> { public: using Container = std::multimap; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using iterator = typename Container::iterator; using const_iterator = typename Container::const_iterator; using key_type = typename Container::key_type; using mapped_type = typename Container::mapped_type; using value_type = typename Container::value_type; using size_type = typename Container::size_type; AZ_FORCE_INLINE iterator begin() { return get().begin(); } AZ_FORCE_INLINE const_iterator begin() const { return get().begin(); } AZ_FORCE_INLINE iterator end() { return get().end(); } AZ_FORCE_INLINE const_iterator end() const { return get().end(); } AZ_FORCE_INLINE iterator erase(iterator it) { return get().erase(it); } AZ_FORCE_INLINE size_t erase(const key_type& key) { return get().erase(key); } AZ_FORCE_INLINE iterator find(const key_type& key) { return get().find(key); } AZ_FORCE_INLINE const_iterator find(const key_type& key) const { return get().find(key); } AZ_FORCE_INLINE void clear() { get().clear(); } AZ_FORCE_INLINE bool empty() const { return get().empty(); } AZ_FORCE_INLINE iterator insert(value_type&& kv) { return get().insert(kv); } AZ_FORCE_INLINE iterator insert(const value_type& kv) { return get().insert(kv); } AZ_FORCE_INLINE size_type size() const { return get().size(); } private: Container& get() const; }; template class StaticInstanceSpecialization> { public: using Container = std::set; using reference = typename Container::reference; using const_reference = typename Container::const_reference; using iterator = typename Container::iterator; using const_iterator = typename Container::const_iterator; using value_type = typename Container::value_type; using size_type = typename Container::size_type; using pair_iter_bool = std::pair; AZ_FORCE_INLINE iterator begin() { return get().begin(); } AZ_FORCE_INLINE const_iterator begin() const { return get().begin(); } AZ_FORCE_INLINE iterator end() { return get().end(); } AZ_FORCE_INLINE const_iterator end() const { return get().end(); } AZ_FORCE_INLINE iterator erase(iterator it) { return get().erase(it); } AZ_FORCE_INLINE size_t erase(const value_type& key) { return get().erase(key); } AZ_FORCE_INLINE iterator find(const value_type& key) { return get().find(key); } AZ_FORCE_INLINE const_iterator find(const value_type& key) const { return get().find(key); } AZ_FORCE_INLINE void clear() { get().clear(); } AZ_FORCE_INLINE bool empty() const { return get().empty(); } AZ_FORCE_INLINE pair_iter_bool insert(value_type&& kv) { return get().insert(kv); } AZ_FORCE_INLINE pair_iter_bool insert(const value_type& kv) { return get().insert(kv); } AZ_FORCE_INLINE size_type size() const { return get().size(); } private: Container& get() const; }; // This is a non-thread safe version of AZStd::static_storage, used purely to lazy // initialize various Cry DLL statics/singletons. They are created on first access. template > class StaticInstance : public StaticInstanceSpecialization { public: template StaticInstance(Args&& ...args) { // We need to pass args as a copy to avoid taking references to values that dont support it. // For example, if an enum value is being passed in args, we would lost the value inside the lambda m_ctor = [=]() { return Create(args...); }; } ~StaticInstance() { if (m_instance) { Destructor()(m_instance); } } AZ_FORCE_INLINE T* operator->() const { return Get(); } AZ_FORCE_INLINE operator T*() const { return Get(); } AZ_FORCE_INLINE operator T&() const { return *Get(); } AZ_FORCE_INLINE T* operator&() const { return Get(); } AZ_FORCE_INLINE operator bool() const { return m_instance != nullptr; } private: StaticInstance(const StaticInstance&) = delete; StaticInstance(StaticInstance&&) = delete; StaticInstance& operator=(const StaticInstance&) = delete; template T* Create(Args&& ...args) const { return new((void*)&m_storage) T(AZStd::forward(args)...); } T* Get() const { if (!m_instance) { m_instance = m_ctor(); } return m_instance; } mutable T* m_instance = nullptr; mutable typename AZStd::aligned_storage::value>::type m_storage; AZStd::function m_ctor; }; template std::vector& StaticInstanceSpecialization>::get() const { return *(*static_cast>*>(this)); } template std::list& StaticInstanceSpecialization>::get() const { return *(*static_cast>*>(this)); } template std::map& StaticInstanceSpecialization>::get() const { return *(*static_cast>*>(this)); } template std::multimap& StaticInstanceSpecialization>::get() const { return *(*static_cast>*>(this)); } template std::set& StaticInstanceSpecialization>::get() const { return *(*static_cast>*>(this)); }