2011-01-18 5 views
1

내 응용 프로그램은 맵 구조에서 특정 수의 항목 만 처리 할 수 ​​있습니다. 내 코드가 그 한계를 지정하여 내 코드가 더 좋아지지 않을 수 있도록하려면 어떻게해야합니까? 유형 맵의 변수를 정의 할 때 최대 제한을 지정하는 방법이 있습니까?STL :: map 컨테이너의 최대 크기를 제한하는 방법이 있습니까?

감사

+1

지도에 N 개 이상의 요소를 넣지 않는 것 외에는 다른가요? –

답변

3

지도에 인스턴스를 만들 때 제한을 설정할 수있는 방법이 없습니다. 액세스 할 때 자신의 안전 경계를 가질 수 있다고 생각합니다. 예 :

if (mymap.find(a) == mymap.end() and mymap.size() >= MAX_MAP_ALLOWED) { 
    throw (runtime_error("map limit exceeded")); 
} else { 
    mymap[a] = b; 
} 

이러한 검사를 캡슐화하는 고유 한지도 클래스를 만들 수 있습니다.

1

STL과 용기는 또한 (부도) 파라미터로서 'allocator'를 가지고. 이 할당자는 컨테이너의 새로운 공간을 데이터에 할당하는 수단입니다.

'뚜껑이있는'할당자를 정의하면 (간단히 들리겠습니까?) 여기 있습니다.

EDIT - 일부 fora에서는 할당자가 초기에 무국적이지만 대부분의 (최신) 컴파일러에서 statefull이 될 수 있음을 발견했습니다. 그것이 내가 계속 이어지는 이유입니다. 하지만이 방법을 사용하는 것은 매우 번거롭고,지도 형식을 cappedmap 어댑터에 집계하는 것이 더 쉽고 간편합니다.

이 여기 저기 나에게 순간을 많이했다, 그러나 여기에서 나는 컴파일, 출장, 예를 가지고 :

// an allocator with maximally MAX elements. 
template< typename T, size_t MAX = 5 > 
struct AllocateCapped { 

    // reuses an existing allocator 
    typedef std::allocator<T> tallocator; 

    typedef typename tallocator::value_type value_type; 
    typedef typename tallocator::pointer pointer; 
    typedef typename tallocator::reference reference; 
    typedef typename tallocator::const_pointer const_pointer; 
    typedef typename tallocator::const_reference const_reference; 
    typedef typename tallocator::size_type size_type; 
    typedef typename tallocator::difference_type difference_type; 

allocator 멤버로 덮인 할당 위임의 실제 코드 :

size_t free; 
    tallocator allocator; 

    AllocateCapped():free(MAX){ 
     printf("capped"); 
    } 

template<typename T2> 
    AllocateCapped(const AllocateCapped<T2>& other){} 

    pointer allocate(size_type n, const_pointer hint = 0) { 
     if(!free) throw std::bad_alloc(); 
     free-=n; 
     return allocator.allocate(n, hint); 
    } 

    void deallocate(pointer p, size_type n) { 
     free+=n; 
     allocator.deallocate(p,n); 
    } 

    size_type max_size() const { return free; } 
    void construct(pointer p, const_reference val) { 
     return allocator.construct(p,val); 
    } 
    void destroy(pointer p) { allocator.destroy(p); } 

    template<class _Other> 
    struct rebind 
    { // convert this type to _ALLOCATOR<_Other> 
     typedef typename AllocateCapped<_Other> other; 
    }; 

}; 

// example structure 
struct s { 
    int i; 
    s():i(){} 
    s(int i):i(i){} 
}; 

int main(int argc, char* argv[]) { 
typedef AllocateCapped< std::pair<const int, s> > talloc; 
talloc a; 
talloc::pointer p = reinterpret_cast<talloc::pointer>(a.allocate(1,0)); 
a.construct(p, talloc::value_type()); 
a.destroy(p); 
a.deallocate(p, 1); 

std::map<int , s, std::less<int>, talloc > m; 
std::vector<int, AllocateCapped<int> > v; 
for(int i = 0; i != 4; ++i) { 
    m[i]=s(i); 
    v.push_back(i); 
} 
m[5]=s(5); // throws 
v.push_back(5); // throws 
return 0; 
} 

참고 :

이 할당은 다음과 같이 사용할 수 없습니다 토르 엄격하게 테스트되었습니다. 그것은 단지 아이디어 일뿐입니다.

+0

흥미 롭습니다. 사용자가'max_size()'를 오버라이드해야합니까? – chrisaycock

+2

아쉽게도 할당자는 컨테이너 단위가 아니므로 크기를 제한하려는 맵 인스턴스마다 별도의 할당 자 유형이 없으면이 접근 방식은 작동하지 않습니다. –

+0

@James : 특수 할당자를 사용하여'map'을'typedef' 할 수 있습니다. –

1

캡핑 된 할당 자 아이디어를 시도한 후에 cappedadaptorstd::map (주의 : 상속하지 않음! 적어도 공개적으로는 아님)을 집계하는 것이 더 간단하다고 생각합니다.

template<typename tKey, typename tVal> class cappedmap { 
    typedef std::map<tKey,tVal> tmap; 
    tmap mymap; 

    cappedmap(size_t amax):mymax(amax){} 

    // adapt the map interface 
    pair<tmap::iterator,bool> insert(tmap::value_type kv) { 
     if(mymap.size() > mymax) throw myexcept(); 
     return mymap.insert(kv); 
    } 

    tVal operator[](tKey k) { 
    tVal v = mymap[k]; 
    if(mymap.size() > mymax) { 
     mymap.remove(k) 
     throw myexcept(); 
    } 
    } 
    ... 
}; 
관련 문제