Is initializing char array from string literal considered to be a implicit conversion?

Viewed 225

Is char x[10] = "banana"; considered to be a implicit conversion from const char[7] to char[10]?

Since std::is_convertible<const char[7], char[10]>::value evaluates to false the obvious answer would be that it isn't, but I couldn't find a proper definition of implicit conversion anywhere. Reading cppreference I'd say that it is because:

Implicit conversions are performed whenever an expression of some type T1 is used in context that does not accept that type, but accepts some other type T2; in particular: ... when initializing a new object of type T2, including return statement in a function returning T2;

although I'm not sure why they didn't exclude explicit constructors from this case.

Follow-up question (which may be useless):

Are arrays completely excluded from any kind of conversions (meaning array-to-array conversions) ?

4 Answers

In this declaration

char x[10] = "banana";

there is no conversion. Elements of the string literal are used to initialize elements of the array. In fact it is equivalent to

char x[10] = { 'b', 'a', 'n', 'a', 'n', 'a', '\0' };

If instead of the array you declared a pointer like

const char *x = "banana";

then the string literal having the type const char[7] would be implicitly converted to a pointer to its first element of the type const char *.

The above declaration is equivalent to

const char *x = &"banana"[0];

Language-lawyerly speaking, initializing char array from string literal is a implicit conversion.

[conv.general]:

An expression E can be implicitly converted to a type T if and only if the declaration T t=E; is well-formed, for some invented temporary variable t ([dcl.init]).

Note that the core language only defines implicit conversion from an expression to a type. So the meaning of "implicit conversion from const char[7] to char[10]" is undefined.

is_convertible<From, To>::value is false whenever To is an array type, because it is defined to produce false if To is not a valid return type, which an array is not. (This can be implemented in different ways.)

[meta.rel]/5:

The predicate condition for a template specialization is_­convertible<From, To> shall be satisfied if and only if the return expression in the following code would be well-formed, including any implicit conversions to the return type of the function:

To test() {
  return declval<From>();
}

Arrays can rarely be the destination of implicit conversions, since they can be neither parameter types nor return types. But they are not excluded from temporary materialization conversion.

I don't have a copy of the newest standard, but in [dcl.init.string], there is the paragraph:

If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized (8.5).
C++.2011§8.5.2¶3

So it is the specified behavior for initializing a char array of known size with a literal.

For the purposes of overload resolution, it is considered to be an implicit conversion, but one that involves no actual conversions (the identity conversion sequence). See [over.ics.list]/4:

Otherwise, if the parameter type is a character array125 and the initializer list has a single element that is an appropriately-typed string-literal (9.4.2), the implicit conversion sequence is the identity conversion.

125 Since there are no parameters of array type, this will only occur as the referenced type of a reference parameter.

The implicit conversion to array type itself (not a reference to array) seems to be pretty restricted: it's apparently only allowed in a variable definition. Something like static_cast<char[10]>("banana") won't compile (at least on GCC and Clang).

Related