views:

304

answers:

5

I have a vector that I am loading with a know amount of elements (N).

The processing dynamically creates new elements, which are appended to the vector.

I am expecting about 2 * N additional elements to be created, so I resize the vector to 3 * N.

If the additional elements exceed that, I would like a program abort, rather than a dynamic expansion of the vector.

Is there a way to detect that, that is portable between AIX/TRU64/Linux?

+3  A: 

Detect what? Whether the vector will be resized? Whether it has been?

The only real way to achieve this is to provide checking functionality either in a custom allocator or a function that adds elements to the vector.

e.g

template<class T> 
void add_element(std::vector<T>& container, T const& v)
{
  if (container.capacity()+1 >= 3*N)
  {
    // terminate/exception/whatever
  }

 container.push_back(v);
}
Andrew Grant
+3  A: 

Create your own class that will delegate to the vector. And check size in your own push_back.

Mykola Golubyev
+2  A: 

If you know the size at compile time, maybe using a std::tr1::array (or boost::array) would be a better choice. It keeps a fixed size and check access like std::vector.

If however you know it only at runtime, as said others here, you should encapsulate your vector in a class with specific functions that will check the conditions you want (via assertions for example).

In this last approach, I would suggest, if you can know the maximum size at the vector creation, to reserve ( std::vector::reserve() ) the maximum size of the vector in your encapsulating class constructor (or initialization function). That way, there will be no more memory manipulations by the vector itself (only if the vector elements constructor/destructor do such manipulations). Then, adding a simple assertion that checks that the vector capacity ( std::vector::capacity() ) never changed at the start and end of all the functions of your class will help you make sure it's memory don't move.

For example (assuming DATA_MAX_SIZE is a default max size defined somewhere) :

template< typename MyType >
class MyData
{
public:
    MyData( unsigned long max_size = DATA_MAX_SIZE )
        : m_max_size( max_size )
        { m_data.reserve( m_max_size ); }

    void add( const MyType& value ) { check_capacity(); m_data.push_back( value ); check_capacity(); }



private:

    std::vector< MyType > m_data;
    const unsigned long m_max_size;

    void check_capacity() { if( m_data.capacity() != m_max_size ) throw Exception("Useful error message here!" ); }

};

Or something like that...

Klaim
+3  A: 

Why are you using a vector? The whole point of the vector is to dynamically expand when needed.

Instead of making a class to delegate to the vector, just make a class to delegate to a simple array. Have your push_back check the size and abort when needed.

Ken
+2  A: 

std classes use an allocator called everytime you insert an element. You can write a new allocator inheriting from the std::alocator, and add all kind of checks/traces you need.

(I did this before but it took me a while to make working code.)

Ben