1

I have a bunch of structs like:

struct A { ... } struct B { ... } struct C { ... } 

I want to devise a function that can accept arrays of these structs and iterate through each element of the array and call another function like:

template <typename T> ostream& process(ostream& os, const T* array) { // output each element of array to os (but how do we know the length?) } A a_array[10]; // in practice, this is actually operator<<, so I cannot pass in the // size explicitly process(..., a_array); 

Update: I cannot use any of the std containers here. It has to be an array unfortunately!

1
  • 3
    Why are you not using std::vector or std::array? Commented Jan 4, 2012 at 17:08

4 Answers 4

10

Array-to-pointer decay is really, really bad.

Fortunately, C++ has array references, which know their size.

template<typename T, size_t N> ostream& process(ostream& os, const T (&arr)[N]) { // use N } 
Sign up to request clarification or add additional context in comments.

9 Comments

I've always seen const T (&arr)[N], but I suppose it works the same.
I've no idea, it's been a really long time since I used that syntax.
I think it is advantageous to drop the const. The template will automatically make the type const if it needs to be, but if you pass in a non-const array I seem to recall it won't know how to handle it.
The notation const T(&arr)[Size] definitely works to deduce the size of a statically sized array. Leaving off the const has the advantage that the constness is correctly deduced, e.g. when getting an end iterator for the array.
@Dietmar: Oh noes! Code bloat! My binary, it might consume a couple more KB, compared to my hundreds of MB of art and such.
|
7

You could use a std::vector<T> instead of an simple array.

template <typename T> ostream& process(ostream& os, const std::vector<T> &array) { for(std::vector<T>::const_iterator iterator = array.begin(); iterator != array.end(); ++iterator) { //... } } 

Or you can go the std::array way (If your compiler support it and N is constant).

template <typename T, int N> ostream& process(ostream& os, const std::array<T, N> &array) { for(std::array<T, N>::const_iterator iterator = array.begin(); iterator != array.end(); ++iterator) { //... } } // Usage: array<int, 10> test; process(..., test); 

2 Comments

why not std::array<T, N>? The size is known and constant.
If the compiler doesn't have std::array, boost::array is always an option
2

You need to use the following format for arrays:

template <typename T, size_t N> void foo(const T (&arr)[N]) { ... } 

Otherwise, size information will be lost.

Comments

0

Or, a simple template bounds checked array.

template< typename T, unsigned int Size > class Array { public: T& operator[]( unsigned int index ) { assert( index < Size ); return mElements[ index ]; } const T& operator[]( unsigned int index ) const { assert( index < Size ); return mElements[ index ]; } unsigned int Capacity() const { return Size; } private: T mElements[ Size ]; }; 

And then

template< typename T, unsigned int Size > void Process( Array< T, Size >& array ) { for( unsigned int i = 0; i < Size; ++i ) { //use array[i] } } 

And to tie it together

Array< int, 10 > array; Process( array ); 

It's a bit of a roll your own solution, but it's probably roughly equivalent (although a less functional array class) to std::Array or boost

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.