4

次の例には、度とラジアンを表す 2 つのテンプレート化されたクラスが含まれており、それらの間でキャストする明示的な変換演算子があります。g++ ( ideone リンクVisual C++ Compiler Nov 2013 CTP (CTP_Nov2013)) でコンパイルおよび実行されますが、プラットフォーム ツールセットとしてVisual Studio 2013 では実行されません。

#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関数は(7.1.2) の場合があります。この場合、直接初期化(8.5)のexplicitためのユーザー定義の変換としてのみ考慮されます。それ以外の場合、ユーザー定義の変換は、割り当てと初期化での使用に制限されません。

8.5初期化子 [dcl.init]

16フ​​ォームで発生する初期化

T x (a);
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 }またはを使用して変数を初期化しますauto r = rads (d);

于 2014-03-24T08:17:54.963 に答える