Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List-initialization of a reference to an array of unknown size: is it supposed to deduce the array size?

The following code compiles fine in Clang and outputs size of int [3] array

#include <iostream>

int main()
{
  const int (&a)[] = { 1, 2, 3 };
  std::cout << sizeof a << std::endl;
}

However, in GCC the declaration compiles fine, but sizeof a doesn't: apparently GCC refuses to "deduce" the array size and ends up with a as a reference to const int [] type, which is incomplete.

What is the intended behavior in such initializations?

9.3.4/3 appears to be the relevant portion of the standard for such cases, but by itself it doesn't seem to answer this conclusively.

like image 965
AnT Avatar asked Nov 07 '22 18:11

AnT


1 Answers

The standard is not entirely clear on this point, and I think GCC's interpretation is likely to be what WG21 intended, but I am not certain.

The relevant section of the standard is [dcl.array], which describes how to determine the type declared by a declaration in which a declarator contains the array-forming operator []. I quote the relevant part:

An array bound may also be omitted when the declarator is followed by an initializer (11.6) or when a declarator for a static data member is followed by a brace-or-equal-initializer (12.2). In both cases the bound is calculated from the number of initial elements (say, N) supplied (11.6.1), and the type of the identifier of D is “array of N T”.

It's not entirely whether this only applies to a declaration of an array itself, or whether it should also apply in the case of a reference to an array, since [dcl.array] must be recursively consulted when interpreting [dcl.ref] (which describes the & and && operators). However, I think that the latter interpretation should be rejected, as we would not expect the initializer to result in a bound being deduced when the [] is buried deeper in the declarator. To wit, consider the contrived example:

int (*a[1])(const int (&)[]) = {0};

Here GCC and Clang agree, and I think common sense agrees also, that the type of a is int (*[1])(const int (&)[]), and not int (*[1])(const int (&)[1]): the fact that a possesses an initializer does not cause the inner array bound to be deduced.

Based on this, I would argue that GCC is correct in not deducing the array bound in your code, so that a has type const int (&)[].

like image 178
Brian Bi Avatar answered Nov 14 '22 23:11

Brian Bi