I'm looking to use some c++11 features in some existing c++ projects, so I started changing compile flags in Clang for some projects, and I keep running into a specific issue regarding C++11's treatment of conversion operators (or cast operators) that I didn't expect to see and don't understand why this is now considered an error when it's been valid C++ code that's not c++11
I've boiled it down to this simple example:
#include <iostream>
#include <vector>
class SerializableFormat
{
public:
size_t i;
};
class A
{
public:
size_t x, y;
A(size_t n) : x(n), y(1) { }
operator const SerializableFormat() const
{
SerializableFormat result;
result.i = x;
if (y)
{
result.i /= y;
}
return result;
}
};
int main(int argc, const char * argv[])
{
std::vector<SerializableFormat> v;
for(size_t i = 0; i < 20; i++)
{
v.push_back(A(i));
}
return 0;
}
-std=c++98
and libstdc++
, there are no issues and this compiles fine.-std=c++11
and libc++
, I get the error No viable conversion from 'A' to 'value_type' (aka 'SerializableFormat')
Just to make it clear-- in case you're thinking about giving SerializableFormat a constructor just for the class A
:
Since the SerializableFormat
class is more suited for conversion to and from various classes, it makes sense for A
(and other classes that wish to be serializable) to have constructors and conversion operators rather than expect SerializableFormat
to cover every type of class that wants to be serializable, so modifying SerializableFormat
to have a special constructor is not a solution.
Can anyone see what I'm doing wrong here?
3. How many parameters does a conversion operator may take? Explanation: 0 parameters does a conversion operator will take.
There are two types of user-defined conversions: Conversion constructors and conversion functions.
A conversion operator, in C#, is an operator that is used to declare a conversion on a user-defined type so that an object of that type can be converted to or from another user-defined type or basic type. The two different types of user-defined conversions include implicit and explicit conversions.
You can define a member function of a class, called a conversion function, that converts from the type of its class to another specified type.
As the comments correctly note, you can get compiling by dropping the const
in the return type of your SerializableFormat
conversion operator:
operator
const
SerializableFormat() const
As to whether clang is correct in this behavior is a matter of some dispute. The issue is being tracked by clang bug report 16682. At this time there is talk of creating a CWG (C++ committee) issue report, but that has not yet been done. I note that this bug report has been open for some time now (2013-07-23), but was updated as recently as 2015-01-28.
In the meantime, practical advice is just never to return by const
-value. This was decent advice for C++98/03, but with move semantics becomes bad advice because it will disable move semantics.
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