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?
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);
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With