Array size Template and references to array

A

amparikh

Hi all,
I was just browsing the archives when I saw one fo the messages posted
recently about array size template et al.

All along, I have been using the usual template to get the size of the
array.
template<typename T, std::size_t N>
std::size_t size_of(T(&)[N])
{
return N;
}

But as one person pointed out, the following definition fails with the
above template, which is what I have always noticed when I use similar
definitions.
int x[5];
int y[size_of(x)]; //fails here

I always went back to the simple way in these definition
int y[sizeof(x)/sizeof(*x)]; //the simple way.

The person who pointed out the error, also had the template that
works.I would like to use this template all the time, but I am not
quite sure, what it is exactly doing. It is trying to get a reference
to an array and then get the size of that array(which itself is a
reference to a char)..Not quite sure. Can somebody explain ?

template <typename T, unsigned N>
char ( & NelemArrayFunc( T ( & )[ N ] ) )[ N ];

#define Nelem( A ) (sizeof( NelemArrayFunc( A ) ))

Thanks.
 
P

__PPS__

I also didn't know that it was possible to do like this.
int x[5];
int y[size_of(x)]; //fails here
for me it works with g++, but doesn't with ms vc71;
.....
basicly
template <typename T, unsigned N>
char ( & NelemArrayFunc( T ( & )[ N ] ) )[ N ];

means declaration of a function that takes a reference to array of N
T's (T[N]) and returns a reference to array of N chars. (references are
used to preseve type info)

and then macro
#define Nelem( A ) (sizeof( NelemArrayFunc( A ) ))
uses sizeof NelemArrayFunc( A ); where NelemArrayFunc is only valid for
arrays. When this function used as an argument to sizeof the only
information used is the function's return type, that is for T[N] it
returns char[N], and sizeof(char[N]) is N



NelemArrayFunc could be written also like this:
template <typename T, unsigned N>
char ( & NelemArrayFunc( T ( & )[ N ] ) )[ N ]{
char x[N];
return x;
}


Between, anyone has a good link for info on declaration of functions
(as for such unusual declaration) and also declaration of pointers to
such functions. For example, how would I need to declare pointer to
NelemArrayFunc???

thanks
 
B

benben

I think the problem is that when you pass a raw array T arr[N] to a
function as an argument the array "degrades" to a pointer T* arr. Therefore
part of the type information (N) is lost. This, however, is not the case
with type passed to class templates. And therefore with some odd looking
code we can implement size_of this way:

template <typename T, int N>
class size_calc;

template <typename T, int N>
class size_calc<T[N]>
{
public:
enum {size = N};
};

template <typename T>
int size_of(const T& t)
{
return size_calc<T>::size;
}

Notice the declaration of size_of hides the fact that t is an array from the
compiler, and hence prevents the type degrading.
 
B

benben

My previous post is completely stupid. Forget it.

Here is what I should have posted:

template <typename T, int N>
int size_of (const T (&arr) [N])
{
return N;
}
 
G

Gianni Mariani

__PPS__ wrote:
....
Between, anyone has a good link for info on declaration of functions
(as for such unusual declaration) and also declaration of pointers to
such functions. For example, how would I need to declare pointer to
NelemArrayFunc???

template <typename T, unsigned N>
char ( & NelemArrayFunc( T ( & )[ N ] ) )[ N ];

char ( & (* XNelemArrayFunc)( int ( & )[ 3 ] ) )[ 3 ];

XNelemArrayFunc = & NelemArrayFunc<int, 3>;
 
G

Gianni Mariani

benben said:
I think the problem is that when you pass a raw array T arr[N] to a
function as an argument the array "degrades" to a pointer T* arr. Therefore
part of the type information (N) is lost. This, however, is not the case
with type passed to class templates. And therefore with some odd looking
code we can implement size_of this way:

template <typename T, int N>
class size_calc;

template <typename T, int N>
class size_calc<T[N]>
{
public:
enum {size = N};
};

template <typename T>
int size_of(const T& t)
{
return size_calc<T>::size;
}

Notice the declaration of size_of hides the fact that t is an array from the
compiler, and hence prevents the type degrading.

return is a run-time expression. sizeof is a compile-time expression so
it can be used wherever a constant is needed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top