7
votes

Since C++17 (more precisely, since p0135r1), array-to-pointer conversion involves temporary materialization - 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 temporary materialization conversion ([conv.rval]) is applied. The result is a pointer to the first element of the array.

Why? Temporary materialization applies only to prvalues - conv.rval:

A prvalue of type T can be converted to an xvalue of type T. This conversion initializes a temporary object ([class.temporary]) of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object. T shall be a complete type.

So, in case of array-to-pointer conversion, to what is the temporary materialization applied? To the resulting pointer prvalue?

Does temporary materialization occur in the following example?

void foo(int *a) {}
int main() {
    int arr[4];
    foo(arr);
}
1
This is partially explained at the end of open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html I think the sentence only applies to prvalue array, which are included in "rvalue of type array of N T".Holt

1 Answers

2
votes

The temporary materialization conversion is applied to the array to be converted if it is a prvalue. This is because a pointer can only point to something actually existent. It is not applied to the resulting pointer value. In your example, the array to be converted is an lvalue, so the conversion is not applied.

In the following code, the array prvalue Arr{0, 1} is converted to int*. The temporary materialization conversion is applied.

void f(int*) {}
int main()
{
    using Arr = int [2];
    f(Arr{0, 1});
}

GCC doesn’t seem to accept this code, but there is no problem with this code according to the standard. See Why does passing a temporary object as an argument need std::move?