chriskirk
chriskirk

Reputation: 761

How can you deduce the size of an array in a function template?

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!

Upvotes: 1

Views: 3110

Answers (4)

Puppy
Puppy

Reputation: 146910

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
}

Upvotes: 10

moshbear
moshbear

Reputation: 3322

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.

Upvotes: 2

DYoung
DYoung

Reputation: 114

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

Upvotes: 0

Fox32
Fox32

Reputation: 13560

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);

Upvotes: 7

Related Questions