2011-01-18 2 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 - На некоторых форумах я обнаружил, что распределители, хотя первоначально планируемые апатриды, могут быть 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 к 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; 
} 

Примечание: не Thor тщательно проверенный. Это просто идея.

+0

Интересно. Пользователь должен будет переопределить 'max_size()'? – chrisaycock

+2

К сожалению, распределители не являются контейнерами, поэтому, если у вас нет отдельного типа распределителя для каждого экземпляра карты, размер которой вы хотите ограничить, этот подход не будет работать. –

+0

@James: Можно было бы «typedef» создать «карту» со специальным распределителем. –

1

После опробования идеи ограниченного распределителя, я думаю, что проще всего заполнить std::map (примечание: не наследовать-из! По крайней мере, не публично) в cappedadaptor.

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(); 
    } 
    } 
    ... 
}; 
Смежные вопросы