I've been playing around with templated explicit conversion operators in my project, to implement explicit conversion from custom variant-like type. The minimal example reproducing my problem looks like the following (in C++14 mode):
#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;
}
The problem I faced is the operator chosen for the static_cast conversion. With the GCC it's sort of expected (1) case. The output is:
operator T
3.14
But Clang refuses to compile this with the following output:
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.
Why Clang considers conversion (2), when it apparently would require additional constructor call in the conversion sequence, while (1) wouldn't? And is it right (and GCC is then wrong) doing so?