Я думаю, что MSV C не соответствует стандарту, отклоняя ваш код, по крайней мере, с C ++ 14. Вы используете версию, более раннюю, чем C ++ 14, и поэтому явно не поддерживает ее, но более поздние версии MSV C по-прежнему выдают ту же ошибку неоднозначности, даже с флагами /std:c++14
или /std:c++latest
и /permissive-
дано, см. h https://godbolt.org/z/fQA4YD. Но также обратите внимание на комментарий в конце этого ответа о более поздних версиях MSV C.
MSV C, кажется, считает, что '\0'
можно преобразовать в значение нулевого указателя , потому что это константа нулевого указателя .
Это приведет к перегрузке find_first_not_of
с wchar_t
в качестве аргумента и перегрузке * const wchar_t*
в качестве аргумента одинаково хорошо соответствует.
Вы можете видеть, что MSV C объясняет неоднозначность, изменяя значение символа на любое значение, кроме нуля, например 'a'
, в этом случае MSV C считает вызов недвусмысленным.
Однако после разрешения CWG выпустить 903 в виде отчета о дефекте соответствующий отрывок в [conv.ptr] / 1 стандарта C ++ 14 (окончательный вариант) и более поздних стандартов ds скажет:
A константа нулевого указателя является целочисленным литералом ([lex.icon]) со значением ноль или значением типа std :: nullptr_t.
'\0'
- это символьный литерал , а не целочисленный литерал . Поэтому она не является константой нулевого указателя и не может быть преобразована в указатель, что делает вызов однозначным.
До решения CWG, выпуск 903, любое выражение константы rvalue целочисленного типа и значения ноль было константой нулевого указателя, так что в этом случае MSV C является правильным, чтобы дать неоднозначность. Но это не объясняет поведение в более новых версиях и с флагами C ++ 14 (или выше).
Это можно решить, используя L'\0'
вместо '\0'
, потому что L'\0'
имеет тип wchar_t
, так что он соответствует перегрузке, ожидающей wchar_t
точно , тогда как перегрузка, ожидающая const wchar_t*
, потребует преобразования (при условии, что преобразование даже разрешено), что делает первое более подходящим и разрешает Двусмысленность.
Упомянутое выше исправление также является тем, что вы должны сделать в любом случае, даже если не было ошибки (хотя это не имеет значения в данном конкретном случае c). Вы не хотите смешивать char
с wchar_t
. При работе с wchar_t
/ wstring
всегда добавляйте L
перед символьными литералами и строковыми литералами, чтобы дать им правильный тип.
Как указано @RaymondChen в комментарии к этот вопрос, более поздние версии MSV C (которые недоступны для godbolt) do реализуют разрешение CWG 903, когда задан флаг /permissive-
, см. Неявное преобразование интегральной константы выражения к нулевому указателю .