Search code examples
c++arraysc++14rvalue-referenceauto

Auto Rvalue Reference (without &&) to an Array in C++14


Answer 1 of the post How to declare array with auto works fine:

template<typename T> using unsized_raw_array = T[];
auto &&z = unsized_raw_array<int>{1, 2, 3};

Trying out the same but without the double ampersand (&&) results in different behavior of clang and gcc:

template<typename T> using unsized_raw_array = T[];
auto   z = unsized_raw_array<int>{1, 2, 3};

I expected this to be an error because it is an rvalue (universal/forwarding/temporary-object) reference and the double ampersand is missing (&&). And that is what happens with gcc 6.3.0:

  • error: taking address of temporary array

However, clang 3.9.1 compiles and executes it successfully, allowing printing the values of the array in the next statements. I only get this warning (in some scenarios I don't even get the warning):

  • warning: pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression [-Waddress-of-array-temporary]

Which compiler is correct?


Solution

  • Clang is correct; see [conv.array]:

    An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

    Even if the array is a temporary, and therefore a prvalue, it is legal to perform the array-to-pointer conversion on it.

    It appears that the restriction on converting array prvalues into pointers was introduced in a patch that resolved gcc bug 53220. It seems that a consensus emerged on the thread that allowing the conversion was dangerous since initializing a pointer variable from the array would not extend the lifetime of the array. However, treating such code as though it is ill-formed is not the correct solution, since, as pointed out later in the thread, it is possible to use this conversion in a safe way, e.g., if the array is being passed to a function that takes a pointer (and therefore will live until the function returns).

    You would probably have to file a new bug against gcc in order to get them to fix the issue.