You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
689 lines
15 KiB
C++
689 lines
15 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
template <class T>
|
|
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 <typename U, class A>
|
|
class StaticInstanceSpecialization<std::vector<U, A>>
|
|
{
|
|
public:
|
|
using Container = std::vector<U, A>;
|
|
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 <class Integral>
|
|
AZ_FORCE_INLINE
|
|
typename AZStd::enable_if<AZStd::is_integral<Integral>::value, reference>::type
|
|
operator[](Integral index)
|
|
{
|
|
return get()[size_type(index)];
|
|
}
|
|
|
|
template <class Integral>
|
|
AZ_FORCE_INLINE
|
|
typename AZStd::enable_if<AZStd::is_integral<Integral>::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 <typename U, class A>
|
|
class StaticInstanceSpecialization<std::list<U, A>>
|
|
{
|
|
public:
|
|
using Container = std::list<U, A>;
|
|
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 K, class V, class Less, class Allocator>
|
|
class StaticInstanceSpecialization<std::map<K, V, Less, Allocator>>
|
|
{
|
|
public:
|
|
using Container = std::map<K, V, Less, Allocator>;
|
|
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<iterator, bool>;
|
|
|
|
|
|
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 <class K2>
|
|
AZ_FORCE_INLINE
|
|
typename AZStd::enable_if<AZStd::is_constructible<key_type, K2>::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 K, class V, class Less, class Allocator>
|
|
class StaticInstanceSpecialization<std::multimap<K, V, Less, Allocator>>
|
|
{
|
|
public:
|
|
using Container = std::multimap<K, V, Less, Allocator>;
|
|
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 T, class Less, class Allocator>
|
|
class StaticInstanceSpecialization<std::set<T, Less, Allocator>>
|
|
{
|
|
public:
|
|
using Container = std::set<T, Less, Allocator>;
|
|
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<iterator, bool>;
|
|
|
|
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 T, class Destructor=AZStd::default_destruct<T>>
|
|
class StaticInstance
|
|
: public StaticInstanceSpecialization<T>
|
|
{
|
|
public:
|
|
template <class ...Args>
|
|
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 <class ...Args>
|
|
T* Create(Args&& ...args) const
|
|
{
|
|
return new((void*)&m_storage) T(AZStd::forward<Args>(args)...);
|
|
}
|
|
|
|
T* Get() const
|
|
{
|
|
if (!m_instance)
|
|
{
|
|
m_instance = m_ctor();
|
|
}
|
|
return m_instance;
|
|
}
|
|
|
|
mutable T* m_instance = nullptr;
|
|
mutable typename AZStd::aligned_storage<sizeof(T), AZStd::alignment_of<T>::value>::type m_storage;
|
|
AZStd::function<T*()> m_ctor;
|
|
};
|
|
|
|
template <typename U, class A>
|
|
std::vector<U, A>& StaticInstanceSpecialization<std::vector<U, A>>::get() const
|
|
{
|
|
return *(*static_cast<const StaticInstance<std::vector<U, A>>*>(this));
|
|
}
|
|
|
|
template <typename U, class A>
|
|
std::list<U, A>& StaticInstanceSpecialization<std::list<U, A>>::get() const
|
|
{
|
|
return *(*static_cast<const StaticInstance<std::list<U, A>>*>(this));
|
|
}
|
|
|
|
template <class K, class V, class Less, class Allocator>
|
|
std::map<K, V, Less, Allocator>& StaticInstanceSpecialization<std::map<K, V, Less, Allocator>>::get() const
|
|
{
|
|
return *(*static_cast<const StaticInstance<std::map<K, V, Less, Allocator>>*>(this));
|
|
}
|
|
|
|
template <class K, class V, class Less, class Allocator>
|
|
std::multimap<K, V, Less, Allocator>& StaticInstanceSpecialization<std::multimap<K, V, Less, Allocator>>::get() const
|
|
{
|
|
return *(*static_cast<const StaticInstance<std::multimap<K, V, Less, Allocator>>*>(this));
|
|
}
|
|
|
|
template <class T, class Less, class Allocator>
|
|
std::set<T, Less, Allocator>& StaticInstanceSpecialization<std::set<T, Less, Allocator>>::get() const
|
|
{
|
|
return *(*static_cast<const StaticInstance<std::set<T, Less, Allocator>>*>(this));
|
|
}
|