Reputation: 68
error C2668: 'std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<:wchar_t>>::find_first_not_of' : ambiguous call to overloaded function
I get this error in Visual Studio 2013, but not in MinGW. What can I do with this?
I tried adding cache.std::wstring::find_first_not_of
, but this did not help.
My code:
wstring cache = key.GetExpandStringValue(L"Path");
int empregnul = 0;
if(cache.find_first_not_of('\0') == wstring::npos)
{
empregnul = 1;
}
Upvotes: 1
Views: 541
Reputation: 22152
I think MSVC is not standard-conform by rejecting your code, at least since C++14. You are using a version that is older than C++14 and therefore clearly doesn't support it, but later MSVC versions still produce the same ambiguity error, even with /std:c++14
or /std:c++latest
and /permissive-
flag given, see hhttps://godbolt.org/z/fQA4YD. But also note the comment at the end of this answer about more recent versions of MSVC.
MSVC seems to think that '\0'
can be converted to a null pointer value, because it is a null pointer constant.
This would make the overload of find_first_not_of
taking wchar_t
as argument and the overload taking const wchar_t*
as argument equally good matches.
You can see that this is MSVC's reasoning for the ambiguity by changing the character value to anything but zero, e.g. 'a'
, in which case MSVC thinks the call is unambiguous.
However, after the resolution of CWG issue 903 as defect report, the relevant passage in [conv.ptr]/1 of the C++14 standard (final draft) and later standards say:
A null pointer constant is an integer literal ([lex.icon]) with value zero or a prvalue of type std::nullptr_t.
'\0'
is a character literal, not an integer literal. Therefore it is not a null pointer constant and cannot be converted to a pointer, making the call unambiguous.
Before the resolution of CWG issue 903 any rvalue constant expression of integer type and value zero was a null pointer constant, so in that case MSVC is correct to give the ambiguity. But that does not explain the behavior in newer versions and with C++14 (or higher) flags.
This can be resolved by using L'\0'
instead of '\0'
, because L'\0'
has type wchar_t
, so that it matches the overload expecting wchar_t
exactly, while the overload expecting const wchar_t*
would require a conversion (assuming the conversion is even allowed), making the former a better match and resolving the ambiguity.
The fix mentioned above is also what you should do anyway, even if there wasn't an error (although it doesn't matter in this specific case). You don't want to mix char
with wchar_t
. When working with wchar_t
/wstring
always add the L
in front of character literals and string literals to give them the correct type.
As pointed out by @RaymondChen in a comment under this question, more recent versions of MSVC (that are not available on godbolt) do implement the resolution of CWG 903 when the /permissive-
flag is given, see Implicit conversion of integral constant expressions to null pointer.
Upvotes: 2