4

以下示例包含两个模板类来表示度数和弧度,并使用显式转换运算符在它们之间进行转换。它使用 g++ ( ideone link )编译和运行,但不能使用 Visual Studio 2013Visual C++ Compiler Nov 2013 CTP (CTP_Nov2013)作为平台工具集。

#include <iostream>

static const double PI = 3.14159265358979323846;

// Forward declarations
template< typename T > class radians;
template< typename T > class degrees;

template< typename T >
class degrees
{
    public:
        degrees(const T value)
            : value_(value)
        {}

        template< typename U >
        explicit operator U() const
        {
            return value_ * PI / 180.0;
        }

        T value() const { return value_; }

    private:
        T value_;
};

template< typename T >
class radians
{
    public:
        radians(const T value)
            : value_(value)
        {}

        template< typename U >
        explicit operator U() const
        {
            return (value_* 180.0) / PI;
        }

        T value() const { return value_; }

    private:
        T value_;
};

template< typename T >
std::ostream& operator<<(std::ostream& out, const radians<T>& r)
{
    return out << r.value() << "r";
}

template< typename T >
std::ostream& operator<<(std::ostream& out, const degrees<T>& r)
{
    return out << r.value() << "d";
}


int main()
{
    using degs = degrees<float>;
    using rads = radians<float>;

    auto d = degs{10};
    auto r = static_cast<rads>(d);

    std::cout << d << std::endl;
    std::cout << r << std::endl;

    return 0;
}

Visual Studio 错误输出:

error C2440: 'static_cast' : cannot convert from 'degrees<float>' to 'rads' degrad.cpp  69  1   degrad
error C3536: 'r': cannot be used before it is initialized   degrad.cpp  72  1   degrad

怎么了?为什么它适用于 g++ 而不是 Visual Studio 2013?哪个编译器在做正确的事情?

4

1 回答 1

7

不接受提及的片段的编译器是错误的,提供的代码是合法的,并且在编译期间不应产生致命的诊断。换句话说; msvc 做错了


标准的相关部分

12.3.2转换函数 [class.conv.fct]

2一个函数可能是explicit(7.1.2),在这种情况下,它只被视为直接初始化(8.5)的用户定义转换。否则,用户定义的转换不限于在赋值和初始化中使用。

8.5初始化器 [dcl.init]

16表单中发生的初始化

T×(一);
T x {a};

以及在new表达式 (5.3.4)、static_cast表达式 (5.2.9)、功能符号类型转换 (5.2.3) 以及基类和成员初始化程序 (12.6.2) 中称为直接初始化


我将如何MSVC++解决有缺陷的问题?

  • 使用typedef radians<float> rads;代替using, 和其中之一;

    • explicit从您的转换功能中删除,或者;

    • auto r = rads { d }使用or初始化变量auto r = rads (d);

于 2014-03-24T08:17:54.963 回答