Der folgende Code wird von MSVC 2017 abgelehnt (aber von GCC/Clang akzeptiert):Überladungsauflösung: passt const/ref nicht besser als eine benutzerdefinierte Konvertierung?
class BA
{
private:
operator int() const;
};
template <typename A, typename B>
class Builder {};
template <typename C>
struct Concatenable;
template <int N> struct Concatenable<char[N]>
{
using type = char[N];
};
template <int N> struct Concatenable<const char [N]>
{
using type = const char[N];
};
template <> struct Concatenable<BA>
{
using type = char *;
};
template<typename A, typename B>
Builder<typename Concatenable<A>::type, typename Concatenable<B>::type>
operator+(const A &, const B &)
{
return {};
}
int main()
{
BA ba;
char array[] = {'a', 'b'};
ba + array;
}
Fehler:
example.cpp
40 : <source>(40): error C2666: 'operator +': 2 overloads have similar conversions
31 : <source>(31): note: could be 'Builder<char *,char [2]> operator +<BA,char[2]>(const A &,const B (&))'
with
[
A=BA,
B=char [2]
]
40 : <source>(40): note: or 'built-in C++ operator+(__int64, char [2])'
40 : <source>(40): note: while trying to match the argument list '(BA, char [2])'
40 : <source>(40): note: note: qualification adjustment (const/volatile) may be causing the ambiguity
Es sieht aus wie MSVC erwägt char[2]
-const char (&)[2]
Einstellung nicht besser als die BA
zu int
Umwandlung. Nach meiner Lektüre des Standards sollte dies nicht wahr sein.
[over.ics.rank] sagt, dass Standard-Konvertierungssequenzen immer bessere Konvertierungen als benutzerdefinierte Konvertierungssequenzen sind; Jetzt:
- die
operator+
aus der Schablone instanziiert verwendet zwei Standard-Konvertierungssequenzen - die eingebauten in einer (über
ptrdiff_t, char *
) eine benutzerdefinierte Konvertierungssequenz und eine Standardkonvertierungssequenz
Deshalb nach den Regeln in [over.match.best] ist meine operator+
immer nicht schlechter als die andere, und es ist besser für einige Argumente, so sollte es bevorzugt werden.
beachte, dass die operator int
aus BA
entfernen oder in ähnlicher Weise um das Array zu const char[]
ändern oder den zweiten Parameter von operator+
Ändern eines Nicht-const nehmen B&
machen MSVC glücklich.
Was sehe ich nicht?
Alternativ Kennzeichnung 'Betreiber int' als' explicit' sollte auch funktionieren (warum implizite benutzerdefinierte Umwandlung Betreiber selbst erlaubt?). Obwohl dies ein Fehler in VC++ zu sein scheint. Wird eine Referenz auch als Konvertierung akzeptiert? – VTT
Es ist eine "Identitätskonvertierung", zumindest aus meiner Lektüre ... http://eel.is/c++draft/over.ics.ref#1 – peppe