Является char x[10] = "banana"; считается неявным преобразованием из const char[7] в char[10]?

Поскольку std::is_convertible<const char[7], char[10]>::value оценивается как false, очевидным ответом будет то, что это не так, но я нигде не смог найти правильного определения неявного преобразования. Читая cppreference, я бы сказал, что это потому, что:

Неявные преобразования выполняются всякий раз, когда выражение некоторого типа T1 используется в контексте, который не принимает этот тип, но принимает некоторый другой тип T2; в частности: ... при инициализации нового объекта типа T2, включая оператор return в функции, возвращающей T2;

Хотя я не уверен, почему они не исключили явные конструкторы из этого случая.

Последующий вопрос (который может оказаться бесполезным):

Полностью ли массивы исключены из любых преобразований (имеется в виду преобразование массива в массив)?

3
domdrag 11 Окт 2021 в 19:25

3 ответа

В этой декларации

char x[10] = "banana";

Нет конверсии. Элементы строкового литерала используются для инициализации элементов массива. Фактически это эквивалентно

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

Если вместо массива вы объявили указатель типа

const char *x = "banana";

Тогда строковый литерал, имеющий тип const char[7], будет неявно преобразован в указатель на его первый элемент типа const char *.

Вышеприведенное объявление эквивалентно

const char *x = &"banana"[0];
3
Ted Lyngmo 11 Окт 2021 в 17:14

У меня нет копии новейшего стандарта, но в [dcl.init.string] есть параграф:

Если инициализаторов меньше, чем элементов массива, каждый элемент, не инициализированный явно, должен быть инициализирован нулем (8.5).
C ++. 2011§8.5.2¶3

Таким образом, это указанное поведение для инициализации массива char известного размера с помощью литерала.

2
jxh 11 Окт 2021 в 16:39

В целях разрешения перегрузки это считается неявным преобразованием, но не включает фактических преобразований (последовательность преобразования идентификаторов). См. [Over.ics.list] / 4:

В противном случае, если тип параметра представляет собой массив символов 125 и список инициализаторов содержит единственный элемент, который является правильно типизированный строковый литерал (9.4.2), неявная последовательность преобразования является преобразованием идентичности.

125 Поскольку нет параметров типа массива, это будет происходить только как ссылочный тип ссылочного параметра.

Неявное преобразование в сам тип массива (а не ссылка на массив) кажется довольно ограниченным: очевидно, оно разрешено только в определении переменной. Что-то вроде static_cast<char[10]>("banana") не компилируется (по крайней мере, на GCC и Clang).

1
Brian Bi 11 Окт 2021 в 17:25