5

C++03 標準ライブラリは、アロケータとなるクラスに型を渡すときに、単純なテンプレート型引数を使用します。これは、テンプレートが C++ でどのように機能するかによって可能になります。ただし、これはそれほど単純ではなく、特に非標準型の場合、型定義が正確にどのように見えるべきかがわからない場合があります。

アダプタ クラスをインストレッドで使用することをお勧めします。私が何を意味するかを示すために、例を作成しました。

#ifndef HPP_ALLOCATOR_ADAPTOR_INCLUDED
#define HPP_ALLOCATOR_ADAPTOR_INCLUDED


#include <memory>


template<typename T>
struct allocator_traits;

template<typename T, class allocator_type = std::allocator<T>>
class allocator_adaptor;


template<>
struct allocator_traits<void>
{
    typedef std::allocator<void>::const_pointer const_pointer;
    typedef std::allocator<void>::pointer       pointer;
    typedef std::allocator<void>::value_type    value_type;
};

template<typename T>
struct allocator_traits
{
    typedef typename std::allocator<T>::const_pointer   const_pointer;
    typedef typename std::allocator<T>::const_reference const_reference;
    typedef typename std::allocator<T>::difference_type difference_type;
    typedef typename std::allocator<T>::pointer         pointer;
    typedef typename std::allocator<T>::reference       reference;
    typedef typename std::allocator<T>::size_type       size_type;
    typedef typename std::allocator<T>::value_type      value_type;
};


template<class allocator_type>
class allocator_adaptor<void, allocator_type>
    : public allocator_traits<void>
{
public:
    template<typename U> struct rebind { typedef allocator_adaptor<U, allocator_type> other; };
};

template<typename T, class allocator_type>
class allocator_adaptor
    : public allocator_traits<T>
{
private:
    allocator_type m_impl;

public:
    template<typename U> struct rebind { typedef allocator_adaptor<U, allocator_type> other; };

    allocator_adaptor() throw() /*noexcept*/;
    allocator_adaptor(allocator_adaptor const&) throw() /*noexcept*/;
    allocator_adaptor(allocator_type const&) throw() /*noexcept*/;
    template<typename U> allocator_adaptor(allocator_adaptor<U, allocator_type> const&) throw() /*noexcept*/;
    ~allocator_adaptor() throw();

    pointer       address(reference x) const /*noexcept*/;
    const_pointer address(const_reference x) const /*noexcept*/;

    pointer   allocate  (size_type, allocator_traits<void>::const_pointer hint = 0);
    void      deallocate(pointer p, size_type n) /*noexcept*/;
    size_type max_size  () const throw() /*noexcept*/;

    template<class U, typename... argument_types> void construct(U* p, argument_types&&... args);
    template<class U> void destroy(U* p);
};


#endif /* HPP_ALLOCATOR_ADAPTOR_INCLUDED */

実装は明らかであるべきです。使用例をいくつか示します。

template<class allocator_type>
int max_size(allocator_type const& alloc)
{
    // we don't know what kind of max_szie function will be called.
    return alloc.max_size();
}

template<typename T>
int max_size(allocator_adaptor<T> const& alloc)
{
    // we know what kind of max_size function will be called.
    return alloc.max_size();
}

これは通常の方法と比較して改善されていますか?

4

2 に答える 2

1

実際、ここでのポイントはconstruct、可変引数に基づいており、代わりに次のように記述できるメンバーを導入することです。

typedef std::allocator<T> my_alloc;
my_alloc alloc;
my_alloc::pointer p = alloc.allocate(10);
alloc::construct(p, T(param1, param2, param3));
alloc::construct(p+1, T(param1, param2, param3));
//...

より簡単な形式:

alloc::construct(p, param1, param2, param3);
alloc::construct(p+1, param1, param2, param3);

これはうれしい機能のようです。一方、すべての初期化パラメーターを移動すると、p+1 オブジェクトの適切な初期化が妨げられます。複数のオブジェクトに対して同じパラメーターの初期化を繰り返したい場合はどうすればよいでしょうか。あなたの現在のアプローチは失敗すると思います(残念ながらコンパイル時ではありません)。

于 2011-06-27T12:07:41.717 に答える
0

私には良さそうです...あなたのデザインがいつ通常の方法で優位になるかについての説明があればいいと思います. 例は私を助けるのに最適です

「しかし、それはそれほど単純ではなく、型定義が正確にどのように見えるべきかわからないかもしれません」

あなたの実装は、std::allocator と比較して -type definition- 部分をどのように改善しますか?説明してください

于 2011-06-26T07:31:02.983 に答える