Почему char {} и char() работают как временная переменная для аргумента char *?
В Visual C++ 2017 (с /std:C++14
или с /std:C++17
) работает следующий код:
void TakePtr(char*); // const or not
int main()
{
TakePtr(char{});
TakePtr(char());
}
Я не понимаю, почему это работает.
По-видимому, следующее также будет работать (как и ожидалось):
void TakeChar(char);
TakeChar(char{});
TakeChar(char());
Как компилятор выводит (или конвертирует) тип char
в char*
, когда char{}
или char()
используются в качестве аргумента?
Теперь, если у меня есть перегрузки char
и char*
, это работает без каких-либо ошибок/предупреждений о неоднозначности:
void TakePtr(char*);
void TakePtr(char);
TakePtr(char{}); // Chooses 'char'
TakePtr(char()); // Chooses 'char'
Почему компилятор в порядке с char{}
для TakePtr(char*)
? И почему он не выдает предупреждение/ошибку при выборе лучшей версии? Такое поведение неизбежно нарушает существующий код.
Конечно, компилятор не доволен:
void TakePtr(char*);
char c{};
TakePtr(c);
Ответы
Ответ 1
Потому что Visual много врет. Особенно старше. Ваш код предлагает clang сообщить об ошибке:
<source>:9:6: error: no matching function for call to 'TakePtr'
TakePtr(char{});
^~~~~~~
<source>:5:6: note: candidate function not viable: no known conversion from 'char' to 'char *' for 1st argument
void TakePtr(char*); // const or not
^
<source>:10:6: error: no matching function for call to 'TakePtr'
TakePtr(char());
^~~~~~~
<source>:5:6: note: candidate function not viable: no known conversion from 'char' to 'char *' for 1st argument
void TakePtr(char*); // const or not
^
2 errors generated.
Visual, как известно, "шаткий" с точки зрения следования стандарту C++, поэтому не стоит слишком на него полагаться. Попробуйте проверить с помощью clang/gcc, просто чтобы быть уверенным.
Ответ 2
Компилятор gnu c версии 6.3.0 не принимает ваш код, что приводит к появлению '-fpermissive', поэтому я предполагаю, что это будет работать только с Visual C++.
Ответ 3
Это просто отставание от MSVC: в С++ 03 было правило, что любое константное выражение целочисленного типа и значения 0 является константой нулевого указателя и, следовательно, может быть преобразовано в char*
. Конечно, char()
подходит - и char{}
означает то же самое, хотя оно никогда не пересекалось с правилом.