Fixing "ambiguous call to overloaded function" error
-
After enabling the
/permissive-
flag in my VS2019, I am getting the following errors for calls toQDomElement::setAttribute
(from Qt 5.15.1):error C2668: 'QDomElement::setAttribute': ambiguous call to overloaded function message : could be 'void QDomElement::setAttribute(const QString &,double)' message : or 'void QDomElement::setAttribute(const QString &,float)' message : or 'void QDomElement::setAttribute(const QString &,uint)' message : or 'void QDomElement::setAttribute(const QString &,int)' message : or 'void QDomElement::setAttribute(const QString &,qulonglong)' message : or 'void QDomElement::setAttribute(const QString &,qlonglong)' message : while trying to match the argument list '(const char *, long)'
The calls to
setAttribute
are typically of the formsomeQDomElement.setAttribute(SOME_CONSTANT_STRING, someLong);
where
SOME_CONSTANT
is defined asstatic const char* SOME_CONSTANT_STRING = "Some Constant String";
and
someLong
is a parameter of typelong
.I have several questions:
- Why exactly is this call ambiguous under the
/permissive-
flag? I assume it means the compiler can't decide what overload to use from a set of overloads that are 'equally far' away from(const char*, long)
. But what would that set then be? Between what two (or more) versions can't the compiler decide? - Why does the error NOT occur when I'm NOT using the
/permissive-
flag? - What would be the clean way to avoid this ambiguity?
- Why exactly is this call ambiguous under the
-
After enabling the
/permissive-
flag in my VS2019, I am getting the following errors for calls toQDomElement::setAttribute
(from Qt 5.15.1):error C2668: 'QDomElement::setAttribute': ambiguous call to overloaded function message : could be 'void QDomElement::setAttribute(const QString &,double)' message : or 'void QDomElement::setAttribute(const QString &,float)' message : or 'void QDomElement::setAttribute(const QString &,uint)' message : or 'void QDomElement::setAttribute(const QString &,int)' message : or 'void QDomElement::setAttribute(const QString &,qulonglong)' message : or 'void QDomElement::setAttribute(const QString &,qlonglong)' message : while trying to match the argument list '(const char *, long)'
The calls to
setAttribute
are typically of the formsomeQDomElement.setAttribute(SOME_CONSTANT_STRING, someLong);
where
SOME_CONSTANT
is defined asstatic const char* SOME_CONSTANT_STRING = "Some Constant String";
and
someLong
is a parameter of typelong
.I have several questions:
- Why exactly is this call ambiguous under the
/permissive-
flag? I assume it means the compiler can't decide what overload to use from a set of overloads that are 'equally far' away from(const char*, long)
. But what would that set then be? Between what two (or more) versions can't the compiler decide? - Why does the error NOT occur when I'm NOT using the
/permissive-
flag? - What would be the clean way to avoid this ambiguity?
@Bart_Vandewoestyne
Forget the first parameter, it's the second parameter which is at issue.You have a
long
. You have shown all the possible matches in the messages. There isn't one which is specifically a[signed] long
, is there? It could coerce along
to any of the types shown. So which one would you like it to pick?Something about your compiler's
/permissive
flag tells it whether to permit this and make a best-guess (I don't know which one it actually picks), or report it to you as ambiguous.To resolve, if you want to pass what is a
long
as a value you should cast that to one of the types you show is accepted, whichever one you want it to select. - Why exactly is this call ambiguous under the
-
@Bart_Vandewoestyne
Forget the first parameter, it's the second parameter which is at issue.You have a
long
. You have shown all the possible matches in the messages. There isn't one which is specifically a[signed] long
, is there? It could coerce along
to any of the types shown. So which one would you like it to pick?Something about your compiler's
/permissive
flag tells it whether to permit this and make a best-guess (I don't know which one it actually picks), or report it to you as ambiguous.To resolve, if you want to pass what is a
long
as a value you should cast that to one of the types you show is accepted, whichever one you want it to select.@JonB said in Fixing "ambiguous call to overloaded function" error:
[...]
Something about your compiler's/permissive
flag tells it whether to permit this and make a best-guess (I don't know which one it actually picks), or report it to you as ambiguous.OK. I can live with that :-) although I find it strange that the compiler just 'picks' one... Looks 'dangerous' to me... and I also don't immediately find something at https://docs.microsoft.com/en-us/cpp/build/reference/microsoft-extensions-to-c-and-cpp?view=msvc-160 that would indicate that VS2019 is less strict on such kind of ambiguity issues and 'simply picks an overload'. If anybody knows where I could find more info on VS2019's (non-standard conforming) behavior concerning these kind of overload resolution issues, feel free to share, as I would be happy to read up on this.
To resolve, if you want to pass what is a
long
as a value you should cast that to one of the types you show is accepted, whichever one you want it to select.OK. I guess to know the 'safest' cast to use, I can probably check (e.g. by setting breakpoints and stepping into the functions) what overload my compiler picks without the
/permissive-
flag, and then simply cast to that type when I'm using the/permissive-
flag. This way, the behavior would stay the same before and after the fix. Feel free to let me know if you have any comments on this approach! -
@JonB said in Fixing "ambiguous call to overloaded function" error:
[...]
Something about your compiler's/permissive
flag tells it whether to permit this and make a best-guess (I don't know which one it actually picks), or report it to you as ambiguous.OK. I can live with that :-) although I find it strange that the compiler just 'picks' one... Looks 'dangerous' to me... and I also don't immediately find something at https://docs.microsoft.com/en-us/cpp/build/reference/microsoft-extensions-to-c-and-cpp?view=msvc-160 that would indicate that VS2019 is less strict on such kind of ambiguity issues and 'simply picks an overload'. If anybody knows where I could find more info on VS2019's (non-standard conforming) behavior concerning these kind of overload resolution issues, feel free to share, as I would be happy to read up on this.
To resolve, if you want to pass what is a
long
as a value you should cast that to one of the types you show is accepted, whichever one you want it to select.OK. I guess to know the 'safest' cast to use, I can probably check (e.g. by setting breakpoints and stepping into the functions) what overload my compiler picks without the
/permissive-
flag, and then simply cast to that type when I'm using the/permissive-
flag. This way, the behavior would stay the same before and after the fix. Feel free to let me know if you have any comments on this approach!@Bart_Vandewoestyne
You feeling it is "dangerous" is precisely why there is a/permissive
flag to control behaviour.I don't know why you picked the reference you did to look at. If you want to know about VS 2019
/permissive
you should read through https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-160./permissive-
opts for strict conformance You will also see it is now the default.If you want to investigate the precise behaviour further, Google for
C2668
, with/withoutpermissive
. -
@JonB said in Fixing "ambiguous call to overloaded function" error:
[...]
Something about your compiler's/permissive
flag tells it whether to permit this and make a best-guess (I don't know which one it actually picks), or report it to you as ambiguous.OK. I can live with that :-) although I find it strange that the compiler just 'picks' one... Looks 'dangerous' to me... and I also don't immediately find something at https://docs.microsoft.com/en-us/cpp/build/reference/microsoft-extensions-to-c-and-cpp?view=msvc-160 that would indicate that VS2019 is less strict on such kind of ambiguity issues and 'simply picks an overload'. If anybody knows where I could find more info on VS2019's (non-standard conforming) behavior concerning these kind of overload resolution issues, feel free to share, as I would be happy to read up on this.
To resolve, if you want to pass what is a
long
as a value you should cast that to one of the types you show is accepted, whichever one you want it to select.OK. I guess to know the 'safest' cast to use, I can probably check (e.g. by setting breakpoints and stepping into the functions) what overload my compiler picks without the
/permissive-
flag, and then simply cast to that type when I'm using the/permissive-
flag. This way, the behavior would stay the same before and after the fix. Feel free to let me know if you have any comments on this approach!@Bart_Vandewoestyne said in Fixing "ambiguous call to overloaded function" error:
[...]
OK. I guess to know the 'safest' cast to use, I can probably check (e.g. by setting breakpoints and stepping into the functions) what overload my compiler picks without the/permissive-
flag, and then simply cast to that type when I'm using the/permissive-
flag. This way, the behavior would stay the same before and after the fix. Feel free to let me know if you have any comments on this approach!For what it's worth, I just added some breakpoints and stepped through the code. If my methodology and stepping were correct, then it looks like the following (inline) overload is chosen:
inline void setAttribute(const QString& name, int value) { setAttribute(name, qlonglong(value)); }
so I guess I'll cast to
int
to fix this... -
@Bart_Vandewoestyne said in Fixing "ambiguous call to overloaded function" error:
[...]
OK. I guess to know the 'safest' cast to use, I can probably check (e.g. by setting breakpoints and stepping into the functions) what overload my compiler picks without the/permissive-
flag, and then simply cast to that type when I'm using the/permissive-
flag. This way, the behavior would stay the same before and after the fix. Feel free to let me know if you have any comments on this approach!For what it's worth, I just added some breakpoints and stepped through the code. If my methodology and stepping were correct, then it looks like the following (inline) overload is chosen:
inline void setAttribute(const QString& name, int value) { setAttribute(name, qlonglong(value)); }
so I guess I'll cast to
int
to fix this...@Bart_Vandewoestyne
I think the specific for the warning which you are looking for is the one in https://docs.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc-160#overload-resolution-involving-integral-overloads-and-long-arguments. -
@Bart_Vandewoestyne
You feeling it is "dangerous" is precisely why there is a/permissive
flag to control behaviour.I don't know why you picked the reference you did to look at. If you want to know about VS 2019
/permissive
you should read through https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-160./permissive-
opts for strict conformance You will also see it is now the default.If you want to investigate the precise behaviour further, Google for
C2668
, with/withoutpermissive
.@JonB said in Fixing "ambiguous call to overloaded function" error:
I don't know why you picked the reference you did to look at.
Well, since VS2019 apparently 'picks' one of the overloads, that seemed like non-standard conforming behavior to me, so I considered that non-standard conforming behavior of VS2019 to be a 'Microsoft extension to C++', hence why I looked at that website. In the meanwhile, I also found https://docs.microsoft.com/en-us/cpp/cpp/nonstandard-behavior?view=msvc-160 but nothing mentioned there about this kind of overload resolution issue too.
If you want to know about VS 2019
/permissive
you should read through https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-160./permissive-
opts for strict conformance You will also see it is now the default.Aha! Yes, it is indeed the default if you create new projects from within VS2019. However, our Visual Studio project files are generated using
qmake
(from Qt 5.15.1)... so it looks like theqmake
-generated VS2019 files do not have this set by default yet? (unless we are doing something wrong/special in our build system). -
@Bart_Vandewoestyne
I think the specific for the warning which you are looking for is the one in https://docs.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc-160#overload-resolution-involving-integral-overloads-and-long-arguments.@JonB said in Fixing "ambiguous call to overloaded function" error:
@Bart_Vandewoestyne
I think the specific for the warning which you are looking for is the one in https://docs.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc-160#overload-resolution-involving-integral-overloads-and-long-arguments.Thanks! exactly the explanation I was looking for!