自定义分配器的模板参数推导
Template argument deduction of custom allocator
有一个自定义分配器class:
template<typename T>
class pool_allocator {
public:
using value_type = T;
using pointer = value_type *;
/* Default constructor */
constexpr pool_allocator( void ) noexcept = default;
/* Converting constructor used for rebinding */
template<typename U>
constexpr pool_allocator( const pool_allocator<U> & ) noexcept {}
[[nodiscard]] pointer allocate( size_t n, [[maybe_unused]] const pointer hint = nullptr ) const noexcept {
return get_pool().allocate( n );
}
void deallocate( pointer ptr, size_t n ) noexcept {
get_pool().deallocate( ptr, n );
}
private:
template<size_t CAPACITY>
memory_pool<value_type, CAPACITY> & get_pool( void ) noexcept;
};
pool_allocator
用作 memory_pool
实现的分配器:
template<typename T, size_t CAPACITY>
class memory_pool {
public:
using element_type = T;
using pointer = element_type *;
static constexpr size_t capacity { CAPACITY };
[[nodiscard]] inline pointer allocate( [[maybe_unused]] size_t n = 1 ) noexcept { ... }
inline void deallocate( pointer ptr, [[maybe_unused]] size_t n = 1 ) noexcept { ... }
};
问题是对于各种大小的特定类型,存在许多内存池实例。例如:
struct sample { /* ... */ };
memory_pool<sample, 10> m_samples; /* Serves for 10 instances of 'sample' type */
曾尝试使用 pool_allocator
从 m_samples
池中分配实例:
allocator_traits<pool_allocator<sample>>::allocate( pool_allocator<sample> {}, 1 );
需要使用分配器“link”具体 memory_pool
实例。让我们考虑一下,类型 T
每次都匹配,但分配器不应知道 memory_pool
容量。所以我的想法是为特定的 memory_pool
类型 get_pool()
声明一个 getter - 在分配器中声明它,但在 .cpp 文件中定义它以实现 link ,类似:
.cpp:
template<> template<>
memory_pool<sample, 10> & pool_allocator<sample>::get_pool( void ) noexcept {
return m_samples; /* The instance being created before */
}
所以我的问题是:如何实现这个?简单地选择使用类型特定 pool_allocator<sample>
来操作相同类型的具体 memory_pool
实例,但不将容量指定为显式 pool_allocator
模板参数...使其推导?要改用 delegate/function 指针吗?还有其他方法吗?
解决方法很简单(只列出重要部分):
template<typename T>
class pool_allocator {
public:
[[nodiscard]] pointer allocate( size_t n, [[maybe_unused]] const pointer hint = nullptr ) const noexcept {
return get_pool().allocate( n );
}
void deallocate( pointer ptr, size_t n ) noexcept {
get_pool().deallocate( ptr, n );
}
private:
static auto & get_pool( void ) noexcept; /* <-- here it comes */
};
然后在 .cpp 文件的某处,专门针对特定类型的 get_pool()
静态成员:
template<>
auto & pool_allocator<sample>::get_pool( void ) noexcept {
return m_samples;
}
如此简单的自动声明就可以了。也许下一步要改进的是用一个概念来约束 get_pool()
return 值,但这是另一回事...
有一个自定义分配器class:
template<typename T>
class pool_allocator {
public:
using value_type = T;
using pointer = value_type *;
/* Default constructor */
constexpr pool_allocator( void ) noexcept = default;
/* Converting constructor used for rebinding */
template<typename U>
constexpr pool_allocator( const pool_allocator<U> & ) noexcept {}
[[nodiscard]] pointer allocate( size_t n, [[maybe_unused]] const pointer hint = nullptr ) const noexcept {
return get_pool().allocate( n );
}
void deallocate( pointer ptr, size_t n ) noexcept {
get_pool().deallocate( ptr, n );
}
private:
template<size_t CAPACITY>
memory_pool<value_type, CAPACITY> & get_pool( void ) noexcept;
};
pool_allocator
用作 memory_pool
实现的分配器:
template<typename T, size_t CAPACITY>
class memory_pool {
public:
using element_type = T;
using pointer = element_type *;
static constexpr size_t capacity { CAPACITY };
[[nodiscard]] inline pointer allocate( [[maybe_unused]] size_t n = 1 ) noexcept { ... }
inline void deallocate( pointer ptr, [[maybe_unused]] size_t n = 1 ) noexcept { ... }
};
问题是对于各种大小的特定类型,存在许多内存池实例。例如:
struct sample { /* ... */ };
memory_pool<sample, 10> m_samples; /* Serves for 10 instances of 'sample' type */
曾尝试使用 pool_allocator
从 m_samples
池中分配实例:
allocator_traits<pool_allocator<sample>>::allocate( pool_allocator<sample> {}, 1 );
需要使用分配器“link”具体 memory_pool
实例。让我们考虑一下,类型 T
每次都匹配,但分配器不应知道 memory_pool
容量。所以我的想法是为特定的 memory_pool
类型 get_pool()
声明一个 getter - 在分配器中声明它,但在 .cpp 文件中定义它以实现 link ,类似:
.cpp:
template<> template<>
memory_pool<sample, 10> & pool_allocator<sample>::get_pool( void ) noexcept {
return m_samples; /* The instance being created before */
}
所以我的问题是:如何实现这个?简单地选择使用类型特定 pool_allocator<sample>
来操作相同类型的具体 memory_pool
实例,但不将容量指定为显式 pool_allocator
模板参数...使其推导?要改用 delegate/function 指针吗?还有其他方法吗?
解决方法很简单(只列出重要部分):
template<typename T>
class pool_allocator {
public:
[[nodiscard]] pointer allocate( size_t n, [[maybe_unused]] const pointer hint = nullptr ) const noexcept {
return get_pool().allocate( n );
}
void deallocate( pointer ptr, size_t n ) noexcept {
get_pool().deallocate( ptr, n );
}
private:
static auto & get_pool( void ) noexcept; /* <-- here it comes */
};
然后在 .cpp 文件的某处,专门针对特定类型的 get_pool()
静态成员:
template<>
auto & pool_allocator<sample>::get_pool( void ) noexcept {
return m_samples;
}
如此简单的自动声明就可以了。也许下一步要改进的是用一个概念来约束 get_pool()
return 值,但这是另一回事...