неоднозначный вызов перегруженной функции find_first_not_of - PullRequest
1 голос
/ 25 января 2020

ошибка C2668: 'std :: basic_string , std :: allocator <: wchar_t >> :: find_first_not_of ': неоднозначный вызов перегруженной функции

Я получаю эту ошибку в Visual Studio 2013, но не в MinGW. Что я могу сделать с этим?

Я пытался добавить cache.std::wstring::find_first_not_of, но это не помогло.

Мой код:

wstring cache = key.GetExpandStringValue(L"Path");
int empregnul = 0;
if(cache.find_first_not_of('\0') == wstring::npos)
{
    empregnul = 1;
}

1 Ответ

2 голосов
/ 25 января 2020

Я думаю, что 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-, см. Неявное преобразование интегральной константы выражения к нулевому указателю .

...