views:

119

answers:

4
// sizeofarray.cpp
#include <iostream>
template <typename T,int N>
int size(T (&Array)[N])
{
  return N;
}

int main()
{
   char p[]="Je suis trop bon, et vous?";
   char q[size(p)]; // (A)
   return 0;
}

I heard that an array size in C++ must be a constant expression. So char q[size(p)] is invalid, am I right? But I got no errors when I tried

 g++ -Wall sizeofarray.cpp

Why?

+8  A: 

I heard that an array size in C++ must be a constant expression.

Correct

So char q[size(p)] is invalid, am I right?

According to ISO C++, yes!

But I got no errors when I tried

g++ -Wall sizeofarray.cpp

That's because g++ supports VLA (Variable Length Array) as an extension.

In C++0x there is constexpr feature with the help of which you can write

constexpr int size(T (&Array)[N])
{
  return N;
}

and then char q[size(p)] would be legal.

EDIT : Also read this article [blog whatever]

Prasoon Saurav
surely sizeof is a constant expression(atleast for a non-vla which standard C++ doesn't even have) ?
nos
@nos : yes :)..
Prasoon Saurav
+1. In the last example `sizeof` should be `size`.
sellibitze
@sellibitze : Thanks, corrected. :)
Prasoon Saurav
+6  A: 

Like Prasoon says, it's not a constant expression. For now, you can get a constant-expression value of the size of an array like this:

template <std::size_t N>
struct type_of_size
{
    typedef char type[N];
};

template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))

Explanation here. You basically encode the size of the array into the size of a type, then get the sizeof of that type, giving you:

char q[sizeof_array(p)];
GMan
Cute hack `:)`, +1.
Prasoon Saurav
A: 

I beg to differ with all the answers here. The code show is perfectly fine except for a minor issue (which is definitely not VLA)

template <typename T,int N> 
int size(T (&Array)[N]) 
{ 
  return N; 
} 

int main() 
{ 
   char p[]="Je suis trop bon, et vous?"; 
   char q[sizeof(p)]; // (A), not sizeof and not size as in OP
   return 0; 
} 

I was wondering that the result of the sizeof is always a const value, and hence the code should be fine.

The above code builds fine on VS 2010 and Comeau(strict mode)

$5.3.3/6- "The result is a constant of type size_t. [Note: size_t is defined in the standard header (18.1)."

Chubsdad
@Chubsdad: I think he probably meant `char q[size(p)]`. I have made the necessary corrections in the OP.
Prasoon Saurav
A: 

I use g++ 4.4.3 and have the following alias so that I never forget to turn on the warnings:

$ alias g++
alias g++='g++ -ansi -pedantic -Wall -W -Wconversion -Wshadow -Wcast-qual -Wwrite-strings'

If compiled with the above, there would be some warnings. Following steps show how different options show different warnings.

Compilation with no warning option does not show any warning

$ \g++ sizeofarray.cpp 

Turning on -Wall

$ \g++ -Wall sizeofarray.cpp
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: unused variable ‘q’

Turning on -Wextra

$ \g++ -Wall -Wextra sizeofarray.cpp 
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: unused variable ‘q’
sizeofarray.cpp: At global scope:
sizeofarray.cpp: In instantiation of ‘int size(T (&)[N]) [with T = char, int N = 27]’:
sizeofarray.cpp:12:   instantiated from here
sizeofarray.cpp:4: warning: unused parameter ‘Array’

Finally turning on -pedantic to catch the real problem

$ \g++ -Wall -Wextra -pedantic  sizeofarray.cpp 
sizeofarray.cpp: In function ‘int main()’:
sizeofarray.cpp:12: warning: ISO C++ forbids variable length array ‘q’
sizeofarray.cpp:12: warning: unused variable ‘q’
sizeofarray.cpp: At global scope:
sizeofarray.cpp: In instantiation of ‘int size(T (&)[N]) [with T = char, int N = 27]’:
sizeofarray.cpp:12:   instantiated from here
sizeofarray.cpp:4: warning: unused parameter ‘Array’
ArunSaha