9

Consider a valid code:

template<size_t size>
void by_numbered_reference(int (&array)[size]);

This function accepts an array as an argument and compiler can deduce the size of it using template argument deduction.

Now it is valid (tested on Apple clang version 3.0) to define such function:

void by_reference(int (&array)[], int size);

Which (should) accept a reference to an unknown size array as an argument. Noting that int[] and int[n] are distinct types and generally are incompatible.

The only way which I found how to invoke this function is:

int * array;
by_reference(reinterpret_cast<int(&)[]>(*array), array_size);
  1. Why does the language accept a reference to an unknown size array as a valid function argument, while there is no straightforward way to define such variable?
  2. Are there any known use cases where this syntax is required?
  3. Why void by_reference(int (*&array), int size) should not be used instead?
  • 4
    "Now it is absolutely valid to define such function" No it's not: `error: parameter ‘array’ includes reference to array of unknown bound ‘int []’` ([link](http://ideone.com/oXirmF)) – gx_ Sep 16 '13 at 13:32
  • clang accepts it, though. IMO it should be valid, it's simply a reference to an incomplete type. `reinterpret_cast` is another story. – jrok Sep 16 '13 at 13:33
  • Could You note which compiler complains about the declaration? – Vytis Valentinavičius Sep 16 '13 at 13:35
  • 2
    "clang accepts it" != "absolutely valid" –  Sep 16 '13 at 13:38
  • @H2CO3 On the other hand, I have to admit that "gcc rejects it" != "absolutely not valid" – gx_ Sep 16 '13 at 13:45
  • 1
    Not an answer to your question, but have you considered using std::array? It is perfectly reasonable to define a template for this amazingly convenient type: all the performance, none of the headaches. – Escualo Sep 16 '13 at 14:43
  • @Arrieta: Well, there is a drawback with std::array -- it is not available on platform I am developing for (iOS < 5), secondly this question is more of `what if` type. My code uses 'arrays by reference' only because the compiler could infer the size of an array (see @nijansen answer). – Vytis Valentinavičius Sep 17 '13 at 06:21

1 Answers1

6

Your assumption is wrong, the program is ill-formed. See C++11 standard 8.3.5/8:

If the type of a parameter includes a type of the form “pointer to array of unknown bound of T” or “reference to array of unknown bound of T,” the program is ill-formed.

clang allows this as a compiler extension. g++, for example, will not accept it.

You can however use templates to deduce the size of the passed array:

template <std::size_t N>
void by_reference(int (&)[N])
{
    // whatever
}
nikolas
  • 8,707
  • 9
  • 50
  • 70
  • The template solution will create different instances of the function `by_reference` for each given `N`, isn't it? i'm not saying that this is wrong, only think that is worth to mention. – PaperBirdMaster Sep 16 '13 at 14:04
  • @PaperBirdMaster Yes, that is true for all templates, which is why I didn't explicitly note that. But you're definitely right. – nikolas Sep 16 '13 at 14:07
  • Is it also valid for C? – knivil Sep 16 '13 at 15:25
  • @knivil C99 standard 6.7.5.3/7 says that arrays as function parameter "shall be adjusted to qualified pointer to type"; for me that reads that only `void by_pointer(int * arr)` would be valid. However, gcc even with all warning and pedantic flags I could think of will still happily accept `void by_pointer(int arr[])`, but `sizeof(arr)` will still be `sizeof(int *)`. Since I'm not a C expert I can't tell who's right here. – nikolas Sep 16 '13 at 16:35
  • @knivil ... and I was wrong! See [this question](http://stackoverflow.com/questions/18833174/can-i-use-arrays-as-a-function-parameter-in-c99) – nikolas Sep 16 '13 at 16:52