Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this explicit conversion operator work with g++ but not Visual Studio 2013?

The following example contains two templated classes to represent degrees and radians with an explicit conversion operator to cast between them. It compiles and runs with g++ (ideone link) but not with Visual Studio 2013 with Visual C++ Compiler Nov 2013 CTP (CTP_Nov2013) as the platform toolset.

#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;
}

The Visual Studio error output:

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

What's wrong? Why does it work with g++ but not Visual Studio 2013? Which compiler is doing the right thing?

like image 725
x-x Avatar asked Mar 21 '23 03:03

x-x


1 Answers

A compiler not accepting the metioned snippet is faulty, the code provided is legal and should not yield a fatal diagnostic during compilation. In other words; msvc is doing it wrong.


RELEVANT SECTIONS OF THE STANDARD

12.3.2 Conversion functions [class.conv.fct]

2 A function may be explicit (7.1.2), in which case it is only considered as a user-defined conversion for direct-initialization (8.5). Otherwise, user-defined conversions are not restricted to use in assignments and initializations.

8.5 Initializers [dcl.init]

16 The initialization that occurs in the forms

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

as well as in new expressions (5.3.4), static_cast expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization.


HOW WOULD I WORK AROUND MSVC++ BEING FAULTY?

  • use typedef radians<float> rads; instead of using, and either;

    • remove explicit from your conversion function, or;

    • initialize your variable using auto r = rads { d } or auto r = rads (d);.

like image 71
Filip Roséen - refp Avatar answered Apr 12 '23 13:04

Filip Roséen - refp