c++ - 显式转换运算符模板的优先级和歧义

标签 c++ c++11 templates overload-resolution explicit-conversion

我一直在我的项目中使用模板化的显式转换运算符,以实现从自定义类变体类型的显式转换。重现我的问题的最小示例如下所示(在 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++ - 显式转换运算符模板的优先级和歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46941515/

相关文章:

c++ - 源码中的防火墙绕过技术

c++ - C++11 中的异步 IO

c++ - boost 协程 2 的意外输出

用于非类型模板参数的 c++ enable_if

c++ - 为什么 std::vector 和 std::string 的比较运算符定义为模板函数?

c++ - 将 nullptr 转换为 bool

c++ - 映射/迭代器增量错误

c++ - 我什么时候应该使用 std::any

c++ - 测试两个迭代器是否来自同一个对象

c++ - 了解工厂方法和静态变量分配的返回值优化 (Visual Studio)