template function problem

template<class T, int size>int getLength(T(&)[size]){return size;}

this template function gets the length of an array. can anyone explain how this works. i know that T would be change with the type pass to this template function so my questions are:

1. how did the variable size of gets the length of the array?
2. why is the reference operator (&) nessesary?
3. why is the reference operator enclosed with ()?

1) This is passing an array by reference. The actual type of the passed array is not really T, but is T[size].

2) So that you pass a reference to the array, rather than a pointer to an array. Since a pointer to an array is just a pointer, the size cannot be determined. But if you pass the whole array by reference, the size is part of the type and can thus be determined.

3) T &v[5] makes an array of 5 references. T (&v)[5] makes one reference to an array of 5 T's. The parenthesis here indicate the difference. The function just has the parameter as unnamed so it seems a little weird.

----------------------------

I remember touching on this topic in another thread recently....

http://cplusplus.com/forum/beginner/17680/

The idea is that T and T[size] are actually 2 different types. Think of it like this:

1
2
3
4
5
typedef int int4[4];

// with the above typedef, the below are the same:
int a[4];
int4 b;


If you know the type is 'int4' then you know that T=int and size=4. This is how the compiler fills in the size number.

The thing is... this ONLY works with arrays. It doesn't work with dynamically allocated buffers:

1
2
int* foo = new int[4];
int len = getLength(foo);  // this doesn't work! 


Or with arrays passed to a function by pointer -- EVEN IF you explicitly give a size in the function param:

1
2
3
4
5
6
7
void myFunc(int myarray[5])
{
  getLength(myarray);  // FAILS!
  // although this would work if 'myarray' is passed by reference
  // ie:      int (&myarray)[5]
  // but then this function suffers from the same problems as getLength
}



Basically.. the above getLength function isn't really very useful because it only gives you a size you'd already know.
But the templated getLength function has lots of use. I use it all the time to avoid
duplicating constants or creating const size_t's (or, shudder, #defines):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
template< typename T, size_t N >
size_t asize( T (&)[ N ] )
    { return N; }


void addRecord()  { /* ... */ }
void deleteRecord() { /* ... */ }
void queryRecord() { /* ... */ }


void doMenu() {
    static struct {
        const char* item,
        void             (*pfn)()
    } items[] = {
        "Add Record", addRecord,
        "Delete Record", deleteRecord,
        "Query Record", queryRecord,
        "Exit", 0
   };

   while( 1 ) {
       for( size_t i = 0; i < asize( items ); ++i ) 
           std::cout << i + 1 << ". " << items[ i ].item << std::endl;
       std::cout << std::endl << "Enter selection: " << std::flush;
       std::string choice;
       std::getline( std::cin, choice );
       try {
           size_t iChoice = boost::lexical_cast<size_t>( choice );
           if( iChoice >= asize( items ) || !iChoice )
                throw std::range_error( "Item out of range" );
           if( items[ iChoice - 1 ].pfn )
               items[ iChoice - 1 ].pfn();
           else return;
      } catch( const std::exception& ) {
           std::cout << "Invalid input, try again." << std::endl << std::endl;
      }
   }
}


(Not the greatest of examples...)

Of course this technique is also useful in template metaprogramming where indeed
the array size may not be known to the code being passed the array.

EDIT: Oh, warning. The above was typed off the top of my head very late at night.
Pardon any syntax or semantic errors.

EDIT2: Ok, fixed one glaring syntax error and two obvious off-by-one errors (just
one reason I rarely use arrays....)
Last edited on
thanks Disch. i knew i already knew the answer, im just not so sure about my own thought. lol.

maybe you're right, it's not that useful anyway.
or maybe someone would like to do this, i dont know why? hehe

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
template<class T, int size>int getLength(T(&)[size]){return size;}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6};
    cout << getLength(arr) << endl;
    return 0;
};



i also research on how to get the length of dynamically allocated buffer and most of them answered that it is impossible. they advice me to keep track of its length instead.

you have any solution to this? thanks again.
Topic archived. No new replies allowed.