Ich habe in meinem Projekt mit expliziten Konvertierungsoperatoren für Templates experimentiert, um eine explizite Konvertierung von benutzerdefinierten variantenähnlichen Typen zu implementieren. Das minimal Beispiel mein Problem reproduzieren sieht wie folgt aus (in C++ 14-Modus):Priorität und Ambiguität von expliziten Konvertierungsoperator-Vorlagen
#include <iostream>
#include <stdexcept>
#include <cmath>
using namespace std;
class A
{
public:
template<typename T> explicit operator T() const // 1
{
cout << "operator T" << endl;
return T();
}
template<typename T> explicit operator const T&() const // 2
{
cout << "operator const T&" << endl;
throw runtime_error("operator const T&");
}
template<typename T> explicit operator T&() // 3
{
cout << "operator T&" << endl;
throw runtime_error("operator T&");
}
};
int main(int, char**)
{
try
{
const A& a = A();
cout << abs(static_cast<double>(a) - 3.14) << endl;
}
catch (const runtime_error&)
{
}
return 0;
}
Das Problem, das ich sah sich der Betreiber für die static_cast Umwandlung gewählt ist. Mit dem GCC ist es ein erwarteter (1) Fall. Die Ausgabe lautet:
operator T
3.14
Aber Clang lehnt dies mit der folgenden Ausgabe zu kompilieren:
main.cpp:37:20: error: ambiguous conversion for static_cast from 'const A' to 'double'
cout << std::abs(static_cast<double>(a) - 3.14) << endl;
^~~~~~~~~~~~~~~~~~~~~~
main.cpp:10:32: note: candidate function [with T = double]
template<typename T> explicit operator T() const
^
main.cpp:16:32: note: candidate function [with T = double]
template<typename T> explicit operator const T&() const
^
1 error generated.
Warum Clang Umwandlung (2) ist die Auffassung, wenn es anscheinend zusätzlichen Konstruktoraufruf in der Umwandlungsfolge erfordern würde, während (1) würde nicht? Und ist es richtig (und GCC ist dann falsch) dies zu tun?
Aber warum würden Sie das überhaupt tun? Was ist der Punkt, der sowohl '' Operator T() '' und '' Operator Const T & '' hat? –
@ArneVogel Die Absicht davon im realen Code war, alternative Umwandlungssequenzen zu liefern, z. B. wenn die Variante "long double" enthält, dann würde 'operator T()' helfen, sie nach "int" zu transformieren. Aber anscheinend missverstehe ich Dinge, die 'static_cast' tatsächlich ausführt, also ist diese Umwandlung in Wert in der Tat überflüssig. – aclex