tags:

views:

139

answers:

5

Is it type[]? For example, could I have

T<int[]>;

for some template T.

A: 

The syntax for declaring arrays is

<type> <variable>[<size>];

When using a template the declaration is, in example

template <class T>
  T var[4];
kiamlaluno
+4  A: 

The type of an "array of type T" is T [dimension], which is what you could pass as template parameters. E.g.:

someTemplate<int [10]> t; // array type as template parameter
int a[5]; // array of 5 ints named 'a'

Arrays need to have a dimension which must be greater than 0. This means that e.g. U u[]; is illegal.

There are cases that might seem like exceptions, the first being parameters:

void f(T[]);

This is a special rule for parameters and f() is actually equivalent to the following:

void f(T*);

Then there is direct inialization of arrays:

int a[] = { 1, 2, 3, 4 };

Here the array size is implicitly given through the number of elements in the initializer, thus the type of a is int[4].

There are also incomplete array types without specificied bounds, but you can't directly create instances of these (see Johannes answer for more):

template<class T> struct X { typedef T type; };
X<int[]>::type a = { 1, 2, 3 };

If you are looking for dynamic arrays, prefer standard containers like std::vector<T> instead.

Georg Fritzsche
So T<int[]>;is not valid code?
What about int[] someArray;?
No, it is not valid.
Georg Fritzsche
What about int someArray[];?
No, it... hey, i am no automaton ;) You can't omit the dimension except for the corner-case of parameters i added above and when you want an array instance the form is `type name[dimension];`.
Georg Fritzsche
Actually, it is valid and sometimes useful to have a zero-dimension array (`int foo[0]`). I've seen this used at the end of a struct definition to give a name to the memory *after* the struct (just make sure the allocation is larger than the struct's size).
Karmastan
@kar: C++03, *§8.3.4* : *"In a declaration `T D` where `D` has the form `D1 [constant-expression-opt]` [...] If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero."* Some compilers support it as an extension but its not valid C++03.
Georg Fritzsche
@Georg: Apparently, it isn't valid C either (§6.7.5.2.1). Interesting.
Karmastan
`T<int[]>` is perfectly valid.
Johannes Schaub - litb
For instance, C++0x's smart pointer uses `unique_ptr<int[]> u(new int[N]);` to tell it to delete the passed pointer by the array delete operator. As a more concrete example, there is nothing wrong with `template<typename T> struct id { typedef T type; }; id<int[]>::type t = { 1, 2, 3 };` (this uses `int[]` as the declaration type and makes it into `int[3]` by counting initializers)
Johannes Schaub - litb
@joh: Ouch, thanks. Don't know why i missed that.
Georg Fritzsche
a zero length array is legal if it is on the heap. Reference: http://herbsutter.com/2009/09/02/when-is-a-zero-length-array-okay/which cites 5.3.4 [expr.new] of the standard.
Francesco
@fra: Dynamic arrays and static arrays are different concepts.
Georg Fritzsche
@georg: yes, in fact your reference is correct. I simply wanted to integrate it :-)
Francesco
+2  A: 

If possible, you might consider instead using dynamic arrays, and passing in a pointer as the templated type. Such as...

T<int*> myVar;
virstulte
+1  A: 

This started as a comment to Georg's answer, but it ran a bit long...

It seems that you may be missing some key abstraction in your mental model of arrays (at least C-style ones). Local arrays are allocated on the stack with a hard-coded size. If you have an array inside a class or struct, the space for the array is part of the object itself (whether on the stack or heap). Global arrays may even be represented directly in the size of the executable.

This means that any time you want to use an array, you must specify its size to the compiler. The only reason you can leave the brackets empty in a parameter list is because functions treat array parameters as pointers. The function would hardly be useful if it could only operate on one size of array.

Templates are no exception. If you want the size of the templated array to vary, you can add an extra template parameter. You still have to specify the size at compile time for any given instance, though.

Cogwheel - Matthew Orlando
+3  A: 

There are two syntaxes to denote array types. The first is the type-id syntax and is used everywhere where the language expects a compile time type, which looks like:

T[constant-expression]
T[]

This specifies an array type that, in the first form, has a number of elements given by an integer constant expression (means it has to be known at compile time). In the second form, it specifies an array type with an unknown number of elements. Similar to class types that you declare without a body, such an array type is said to be incomplete, and you cannot create arrays of that type

// not valid: what size would it have?
int a[];

You can, however, specify that type. For example you may typedef it

typedef int unknown_int_array[];

In the same manner, you may specify it as a template type argument, so the answer to your question is yes you can pass such a type specifier to a template. Notice that i talk about specifiers here, because the form you use here is not the type itself.

The second way is using the new-type-id syntax which allows denoting runtime types by having non-constant bounds

T[expression]

This allows passing variables as element count, and also allows passing a zero. In such a case, a zero element array is created. That syntax is only usable with the new operator for supporting dynamic arrays.

Johannes Schaub - litb