【问题标题】:Template argument deduction of custom allocator自定义分配器的模板参数推导
【发布时间】:2021-07-13 22:26:55
【问题描述】:

有一个自定义分配器类:

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_allocatorm_samples 池中分配实例:

allocator_traits<pool_allocator<sample>>::allocate( pool_allocator<sample> {}, 1 );

需要将具体的memory_pool 实例与分配器“链接”。让我们考虑一下,T 类型每次都匹配,但分配器不应知道memory_pool 容量。所以我的想法是为特定的memory_pool 类型get_pool() 声明一个getter - 在分配器中声明它,但在.cpp 文件中定义它以实现链接,例如:

.cpp:

template<> template<>
memory_pool<sample, 10> & pool_allocator<sample>::get_pool( void ) noexcept {
    return m_samples; /* The instance being created before */
}

所以我的问题是:如何实现?只需选择使用特定类型的pool_allocator&lt;sample&gt; 来操作相同类型的具体memory_pool 实例,但不将容量指定为显式pool_allocator 模板参数...以使其推断?要改用委托/函数指针吗?还有其他方法吗?

【问题讨论】:

    标签: c++ templates c++20 template-argument-deduction


    【解决方案1】:

    解决方法很简单(只列出重要部分):

    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() 返回值,但这是另一回事......

    【讨论】:

      猜你喜欢
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-03
      • 2020-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多