Шаблон проектирования C ++ для аргументов типа распределителя - PullRequest
5 голосов
/ 13 июня 2011

Стандартная библиотека C ++ 03 использует простые аргументы типа шаблона при передаче типа в класс, который должен быть распределителем.Это возможно из-за того, как шаблоны работают в C ++.Однако, это не очень просто, и вы можете не знать, как именно должно выглядеть определение типа - особенно в случае нестандартных типов.

Я подумал, что было бы неплохо использовать классы адаптераinstread.Я создал пример, чтобы показать вам, что я имею в виду:

#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();
}

Это улучшение по сравнению с обычным способом?

Ответы [ 2 ]

1 голос
/ 27 июня 2011

На самом деле ваша цель здесь - ввести элемент 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. Что делать, если я хочу повторить инициализацию для тех же параметров для нескольких объектов. Я думаю, что ваш текущий подход потерпит неудачу (и, к сожалению, не во время компиляции).

0 голосов
/ 26 июня 2011

выглядит хорошо для меня ... было бы неплохо получить объяснение того, когда ваш дизайн будет иметь преимущество перед обычным способом. пример будет здорово помочь мне

"Однако это не очень просто, и вы не можете знать, что именно определение типа должен выглядеть как "

как ваша реализация улучшает часть определения -type по сравнению с std :: allocator, пожалуйста, объясните

...