October 1, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Utility Libraries for BREW - A Vector Class

  • March 25, 2003
  • By Radu Braniste
  • Send Email »
  • More Articles »

...and the details

BrewVector goals are the same as for the string implementation we presented last time[4]:

  • minimum impact when used on the stack (sizeof(BrewVector) = sizeof(raw pointer)
  • efficient
  • easy to use
  • integration with POD (plain old data)
  • minimal implementation — no use of iterators or algorithms

Let's analyze these requests one by one.

BrewVector keeps the same internal representation as BrewString, so that sizeof(BrewVector) = sizeof(raw pointer). As usual an informal comparison between BrewVector and two std::vector implementations was conducted (see [4]). BrewVector is as fast as the fastest std::vector and between 2 and 3 times faster than the other.

As BREW development has its roots in C and POD is widely used BrewVector carefully considers integration with POD. Data manipulators accept usually both vectors and POD. For example:

int *iar = new int[3];
iar[0] = 4;
iar[1] = 44;
iar[2] = 444; 
Bint bi2(iar, 3); //constructs a vector from the first 3 elements of iar
Bint bi(10); 
Bint bi3(bi2);
Bint bi4(bi2, 2); //a vector from the first 2 elements of bi2

Similar constructs are accepted for assign (the assignment operator was replaced with this function from the very motive of this flexibility), insert and append. A very interesting constructor, inherited from BrewString and used to efficiently implement operator+() (allows return value optimization) is:

template <class U, class V>
BrewVector (const U& lhs, UINT lnl, const V& rhs, UINT lnr);

It can be used with any combination of POD/BrewVector as in:

Bint bi5 (iar, 2, bi2, bi2.size());

This generalization allows a great deal of flexibility that otherwise should have been implemented using iterators.

The BrewVector<T*> specialization

BrewVector can easily be used for pointers as it is. Unfortunately there are many dangers associated with this use, for example:

BrewVector<int*> bi(a3elementsvector);
bi.append(new int(2));
bi.setSize(2); // memory leak < silently deleting bi[3]

A specialization using void*, as discussed above, was provided under the name BrewPVector. There are 2 reasons:

  • Some compilers don't have full support for partial template specialization
  • There might be users preferring for different reasons the full implementation of BrewVector

BrewPVector is a reduced (and safer) version of BrewVector. For example there are no inserts or assignments. A separate setAt() method was provided to change elements — setAt does index range checking. No remove() and setSize too, only a simple and minimal interface avoiding (almost) all the potential traps.

There is an interesting policy of type ReallocPolicy used internally by BrewVector. Usually the capacity of std::vector is doubled any time the vector has to grow when using the default allocation. Keeping in mind the BREW memory limitations BrewVector allows a policy based on a threshold: allow one way to increase capacity up to some point and a different one after that. One naove example might be:

struct ReallocPolicy_200
{
   static UINT setSize(UINT size) 
   {
      if (size < 200)
         return 2*size;
      return size+10;
   }
};

typedef BrewVector<int, ReallocPolicy_200> Bint200;
Bint200 bi; //capacity will double up to 200 elements
            //capacity incremented by 10 after that 

BrewVector has even a for_each implementation — in this case is a member function defined like:

template < class F >
   F forEach(F func, UINT strt = 0, UINT end =0 );

where F is a functor.

It can be used like:

Writer writer(m_pIShell); 
typedef BrewPVector<int, ReallocPolicy_2> Bpv;
Bpv bi;
bi.ensureCapacity(3);
bi.append( new int(100));
bi.append( new int(2));
bi.append( new int(3));
typedef oOut<2> ppOut;
bi.forEach(ppOut(100, writer)).drawLine();
delete bi[2];
bi.setAt(new int(88), 2);
bi.forEach(ppOut(101, writer)).drawLine();
bi.forEach(del());

Other interesting applications of forEach are in the source code, notably an output technique based on Int2Type[5]. Please note that the provided implementation is VC6.0 compatible — for VC7.x contact the author.

Possible future enhancements:

BrewVector can easily be extended to accept ranges.

References:

[1] Scott Meyers — Effective STL ; Addison-Wesley, 2001

[2] Christopher Smith — Program in Embedded C++ for Smaller and Faster Code http://www.spacetools.com/site/contact_v1_5/V1_5p42.pdf

[3] Reducing C++ Code Bloat 7mdash; http://www.spacetools.com/site/contact_v1_5/V1_5p42.pdf

[4] Utility Libraries for BREW — A String Class

[5] Andrei Alexandrescu - Modern C++ Design, STL ; Addison-Wesley, 2001


Downloads: Source Code - 290 kb.

About the Author

Radu Braniste is Director of Technology at Epicad. He can be contacted at rbraniste@epicad.com

# # #





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel