+} // namespace detail
+
+template <
+ typename T,
+ bool EagerRecycleWhenTrivial = false,
+ bool EagerRecycleWhenNotTrivial = true>
+struct IndexedMemPoolTraits {
+ static constexpr bool eagerRecycle() {
+ return std::is_trivial<T>::value ? EagerRecycleWhenTrivial
+ : EagerRecycleWhenNotTrivial;
+ }
+
+ /// Called when the element pointed to by ptr is allocated for the
+ /// first time.
+ static void initialize(T* ptr) {
+ if (!eagerRecycle()) {
+ new (ptr) T();
+ }
+ }
+
+ /// Called when the element pointed to by ptr is freed at the pool
+ /// destruction time.
+ static void cleanup(T* ptr) {
+ if (!eagerRecycle()) {
+ ptr->~T();
+ }
+ }
+
+ /// Called when the element is allocated with the arguments forwarded from
+ /// IndexedMemPool::allocElem.
+ template <typename... Args>
+ static void onAllocate(T* ptr, Args&&... args) {
+ static_assert(
+ sizeof...(Args) == 0 || eagerRecycle(),
+ "emplace-style allocation requires eager recycle, "
+ "which is defaulted only for non-trivial types");
+ if (eagerRecycle()) {
+ new (ptr) T(std::forward<Args>(args)...);
+ }
+ }
+
+ /// Called when the element is recycled.
+ static void onRecycle(T* ptr) {
+ if (eagerRecycle()) {
+ ptr->~T();
+ }
+ }
+};
+
+/// IndexedMemPool traits that implements the lazy lifecycle strategy. In this
+/// strategy elements are default-constructed the first time they are allocated,
+/// and destroyed when the pool itself is destroyed.
+template <typename T>
+using IndexedMemPoolTraitsLazyRecycle = IndexedMemPoolTraits<T, false, false>;
+
+/// IndexedMemPool traits that implements the eager lifecycle strategy. In this
+/// strategy elements are constructed when they are allocated from the pool and
+/// destroyed when recycled.
+template <typename T>
+using IndexedMemPoolTraitsEagerRecycle = IndexedMemPoolTraits<T, true, true>;