Because we cannot copy an array, a function cannot return an array. However, a function can return a pointer or a reference to an array (§ 3.5.1, p. 114). Unfortunately, the syntax used to define functions that return pointers or references to arrays can be intimidating. Fortunately, there are ways to simplify such declarations. The most straightforward way is to use a type alias (§ 2.5.1, p. 67):
typedef int arrT[10]; // arrT is a synonym for the type array of ten ints
using arrT = int[10]; // equivalent declaration of arrT; see § 2.5.1 (p. 68)
arrT* func(int i); // func returns a pointer to an array of ten ints
Here arrT
is a synonym for an array of ten int
s. Because we cannot return an array, we define the return type as a pointer to this type. Thus, func
is a function that takes a single int
argument and returns a pointer to an array of ten int
s.
To declare func
without using a type alias, we must remember that the dimension of an array follows the name being defined:
int arr[10]; // arr is an array of ten ints
int *p1[10]; // p1 is an array of ten pointers
int (*p2)[10] = &arr; // p2 points to an array of ten ints
As with these declarations, if we want to define a function that returns a pointer to an array, the dimension must follow the function’s name. However, a function includes a parameter list, which also follows the name. The parameter list precedes the dimension. Hence, the form of a function that returns a pointer to an array is:
Type (*function(parameter_list))[dimension]
As in any other array declaration, Type is the type of the elements and dimension is the size of the array. The parentheses around (*
function (
parameter_list))
are necessary for the same reason that they were required when we defined p2
. Without them, we would be defining a function that returns an array of pointers.
As a concrete example, the following declares func
without using a type alias:
int (*func(int i))[10];
To understand this declaration, it can be helpful to think about it as follows:
• func(int)
says that we can call func
with an int
argument.
• (*func(int))
says we can dereference the result of that call.
• (*func(int))[10]
says that dereferencing the result of a call to func
yields an array of size ten.
• int (*func(int))[10]
says the element type in that array is int
.
Under the new standard, another way to simplify the declaration of func
is by using a trailing return type. Trailing returns can be defined for any function, but are most useful for functions with complicated return types, such as pointers (or references) to arrays. A trailing return type follows the parameter list and is preceded by ->
. To signal that the return follows the parameter list, we use auto
where the return type ordinarily appears:
// fcn takes an int argument and returns a pointer to an array of ten ints
auto func(int i) -> int(*)[10];
Because the return type comes after the parameter list, it is easier to see that func
returns a pointer and that that pointer points to an array of ten int
s.
decltype
As another alternative, if we know the array(s) to which our function can return a pointer, we can use decltype
to declare the return type. For example, the following function returns a pointer to one of two arrays, depending on the value of its parameter:
int odd[] = {1,3,5,7,9};
int even[] = {0,2,4,6,8};
// returns a pointer to an array of five int elements
decltype(odd) *arrPtr(int i)
{
return (i % 2) ? &odd : &even; // returns a pointer to the array
}
The return type for arrPtr
uses decltype
to say that the function returns a pointer to whatever type odd
has. That object is an array, so arrPtr
returns a pointer to an array of five int
s. The only tricky part is that we must remember that decltype
does not automatically convert an array to its corresponding pointer type. The type returned by decltype
is an array type, to which we must add a *
to indicate that arrPtr
returns a pointer.
Exercise 6.36: Write the declaration for a function that returns a reference to an array of ten string
s, without using either a trailing return, decltype
, or a type alias.
Exercise 6.37: Write three additional declarations for the function in the previous exercise. One should use a type alias, one should use a trailing return, and the third should use decltype
. Which form do you prefer and why?
Exercise 6.38: Revise the arrPtr
function on to return a reference to the array.