2011-06-13 41 views
5

C++ 03標準庫在將類型傳遞給要作爲分配器的類時使用簡單模板類型參數。這可能是因爲模板在C++中的工作方式。然而,它並不是非常簡單,你可能不知道類型定義應該是什麼樣 - 特別是在非標準類型的情況下。分配器類型參數的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(); 
} 

與通常的方式相比,這是一個進步嗎?

+0

我看不出有什麼不對,但是在C++ 0x時使用'auto'使得大多數STL的使用非常簡單。 – AJG85 2011-06-13 19:20:51

回答

0

對我來說很不錯... 當你的設計在通常的方式上有優勢的時候,這將是很好的解釋。一個例子是巨大的,幫我

「不過,這是不是很簡單 ,你可能不知道 確切類型定義 應該是什麼樣子」

怎麼做與std :: allocator相比,您的實現在類型定義部分得到改進,請解釋

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對象。如果我想重複初始化多個對象的相同參數,該怎麼辦?我認爲你目前的方法會失敗(不幸的是不是在編譯時)。

+0

我不知道你的意思是什麼;)前向聲明和當前C++ 0x草稿中的完全一樣。我認爲你正在用可變參數模板進行交流。 – 0xbadf00d 2011-06-28 13:31:22

+0

你能指點我的標準文章嗎?可能是我真的很困惑。 – ovanes 2011-06-29 18:18:34

+0

當然,您可以在C++ 0x草稿中的「14.5.3可變模板」中找到它(http://www.open-std.org/jtc1/sc22/WG21/docs/papers/2011/n3242.pdf ) – 0xbadf00d 2011-06-30 05:08:48