2011-06-13 2 views
2

현재 임의 표준 준수 배열 유형을 확장하는 최선의 방법을 찾고 있습니다. 명확하게 : 나는 커스텀 할당자를 쓰고 싶지 않다. 나는 단지 기존 확장이나 특정 동작을 "추가"하고 싶습니다. 어떻게 생겼는지 샘플을 만들었습니다. 다음 코드는 단지 설명을위한 것입니다. C++ 임의의 표준을 확장하기위한 디자인 패턴 준수 배열

#ifndef HPP_SMART_ALLOCATOR_INCLUDED 
#define HPP_SMART_ALLOCATOR_INCLUDED 


#include <memory> 
#include <map> 


template<typename T> 
struct allocator_traits; 

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


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 smart_allocator<void, allocator_type> 
    : public allocator_traits<void> 
{ 
public: 
    template<typename U> struct rebind { typedef smart_allocator<U, typename allocator_type::rebind<U>::other> other; }; 
}; 

template<typename T, class allocator_type> 
class smart_allocator 
    : public allocator_traits<T>, 
     private allocator_type 
{ 
public: 
    using typename allocator_traits<T>::const_pointer; 
    using typename allocator_traits<T>::const_reference; 
    using typename allocator_traits<T>::difference_type; 
    using typename allocator_traits<T>::pointer; 
    using typename allocator_traits<T>::reference; 
    using typename allocator_traits<T>::size_type; 
    using typename allocator_traits<T>::value_type; 
    template<typename U> struct rebind { typedef smart_allocator<U, typename allocator_type::rebind<U>::other> other; }; 

    smart_allocator() throw() /*noexcept*/; 
    smart_allocator(allocator_type const&) throw() /*noexcept*/; 
    virtual ~smart_allocator() throw(); 

    virtual ~smart_allocator() 
    { 
     std::map<pointer, size_type>::iterator i = this->m_map.begin(); 
     while (i != this->m_map.end()) 
     { 
      this->allocator_type::deallocate(i->first, i->second); 
      ++i; 
     } 
    } 

    pointer allocate(size_type n, allocator_traits<void>::const_pointer hint = 0) 
    { 
     pointer p = this->allocator_type::allocate(n, hint); 
     this->m_map.insert(std::pair<pointer, size_type>(p, n)); 
     return p; 
    } 

    void deallocate(pointer p, size_type n) /*noexcept*/ 
    { 
     std::map<pointer, size_type>::iterator iter = this->m_map.find(p); 
     if (iter != this->m_map.end()) 
      this->allocator_type::deallocate(iter->first, iter->second); 
    } 

    using allocator_type::address; 
    using allocator_type::construct; 
    using allocator_type::destroy; 
    using allocator_type::max_size; 

private: 
    smart_allocator(smart_allocator const&) throw(); 
    smart_allocator& operator=(smart_allocator const&); 

    std::map<pointer, size_type> m_map; 
}; 


#endif /* HPP_SMART_ALLOCATOR_INCLUDED */ 

다음과 같은 사항을 고려하십시오 :

  • 템플릿 인수 allocator_type는 모든 표준 유형을 일치 될 수 있습니다. std :: allocator에 국한되지 않습니다. 이것은 모든 STL 구현이 사용하고있는 것과 동일한 기술입니다.
  • allocator_type에서 파생 될 때 private 상속을 사용해야합니다. 왜냐하면 std :: allocator 멤버 함수 중 일부는 가상이기 때문입니다. 그러나 std :: allocator & alloc = smart_allocator()는 예상 한대로 수행하지 않습니다.

적용 하시겠습니까?

답변

1

확실하게 복사 생성자와 복사 할당 연산자를 구현해야합니다. 그렇지 않으면 컨테이너가 할당자를 값으로 전달할 때지도가 맹 글링 될 수 있습니다 (특히 이중 삭제가 가능함). 내가 알아 차리지 못했던 다른 고려 사항이있을 수 있습니다.

+0

흠, 내가 처음 게시물에 말한 것처럼 : 그것은 단지 일러스트레이션 목적을위한 것입니다. 그렇다고 절대적으로 옳지 않다는 의미는 아닙니다. 구현해야하는 ctor 선언을 추가했습니다. – 0xbadf00d

1

바로 마음에 무엇이 왔는지는 Decorator입니다. 레퍼런스 노트에서 "Decorator는 원래 객체의 코드를 다시 작성하지 않고 객체를 새로운 상황에 적용하는 데 유용합니다." 내가 당신의 질문을 이해하면, 당신이 무엇을하고있는 것처럼 들립니다.

+0

가상이 아닌 특정 기능의 동작을 확장해야 할 때 작동하지 않습니다. 이것이 std :: allocator의 예입니다. 그러나이 패턴은 추상 기본 클래스를 구현하는 객체의 인스턴스를 전달하여 만들어야하지만 표준 준수 할당 자 클래스는 기본 구성 가능해야합니다. – 0xbadf00d