显式转换运算符模板的优先级和歧义
Priority and ambiguity of explicit conversion operator templates
我一直在我的项目中使用模板化的显式转换运算符,以实现从自定义类变体类型的显式转换。重现我的问题的最小示例如下所示(在 C++14 模式下):
#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;
}
我遇到的问题是为 static_cast 转换选择的运算符。对于 GCC,这是一种预期的 (1) 情况。输出为:
operator T
3.14
但 Clang 拒绝使用以下输出编译它:
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.
为什么 Clang 考虑转换 (2),因为它显然需要在转换序列中调用额外的构造函数,而 (1) 不需要?这样做是对的(然后 GCC 是错的)吗?
static_cast
执行隐式转换或直接初始化。在您的情况下,隐式转换不可行,但直接初始化 是 因为 static_cast
考虑 explicit constructors and conversion functions。所以我的猜测是 clang(在我看来是正确的)识别出有两种可能的直接初始化并相应地抱怨。不确定 GCC 内部发生了什么,也许它默认为 operator T()
如果它能找到一个,不管其他是否存在。
我一直在我的项目中使用模板化的显式转换运算符,以实现从自定义类变体类型的显式转换。重现我的问题的最小示例如下所示(在 C++14 模式下):
#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;
}
我遇到的问题是为 static_cast 转换选择的运算符。对于 GCC,这是一种预期的 (1) 情况。输出为:
operator T
3.14
但 Clang 拒绝使用以下输出编译它:
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.
为什么 Clang 考虑转换 (2),因为它显然需要在转换序列中调用额外的构造函数,而 (1) 不需要?这样做是对的(然后 GCC 是错的)吗?
static_cast
执行隐式转换或直接初始化。在您的情况下,隐式转换不可行,但直接初始化 是 因为 static_cast
考虑 explicit constructors and conversion functions。所以我的猜测是 clang(在我看来是正确的)识别出有两种可能的直接初始化并相应地抱怨。不确定 GCC 内部发生了什么,也许它默认为 operator T()
如果它能找到一个,不管其他是否存在。