Почему char {} и char () работают как временная переменная для аргумента char *? - PullRequest
18 голосов
/ 21 июня 2019

В 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);

Ответы [ 2 ]

13 голосов
/ 21 июня 2019

Потому что 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, просто чтобы быть уверенным.

3 голосов
/ 22 июня 2019

Это просто отставание MSVC: в C ++ 03 было правило, что любое константное выражение целочисленного типа и значения 0 является константой нулевого указателя и поэтому может быть преобразовано в char*. Конечно, char() квалифицируется - и char{} означает то же самое, хотя оно никогда не пересекалось с правилом.

...