显式转换运算符模板的优先级和模糊性

时间:2017-10-25 20:29:05

标签: 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转换选择的运算符。对于海湾合作委员会来说,这是一种预期的(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是错的)吗?

1 个答案:

答案 0 :(得分:0)

:''执行隐式转换或直接初始化。在您的情况下,隐式转换不可行,但直接初始化,因为static_cast会考虑explicit constructors and conversion functions。所以我的猜测是clang(在我看来是正确的)确定有两种可能的直接初始化和相应的抱怨。不确定GCC内部发生了什么,如果可以找到一个,可能默认为static_cast,无论其他是否存在。