C++;11对C++;98转换运算符行为更改? 我想在一些C++项目中使用一些C++ 11特性,所以我开始在CLAN中更改一些项目的编译标志,并且我一直在运行一个关于C++ 11对转换运算符(或CAST运算符)的处理的特定问题。这是我不希望看到的,也不明白为什么现在它被认为是一个错误,当它是不是C++ 11的< C++ >

C++;11对C++;98转换运算符行为更改? 我想在一些C++项目中使用一些C++ 11特性,所以我开始在CLAN中更改一些项目的编译标志,并且我一直在运行一个关于C++ 11对转换运算符(或CAST运算符)的处理的特定问题。这是我不希望看到的,也不明白为什么现在它被认为是一个错误,当它是不是C++ 11的< C++ >,c++,c++11,llvm,libstdc++,libc++,C++,C++11,Llvm,Libstdc++,Libc++,我把它归结为一个简单的例子: #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 { S

我把它归结为一个简单的例子:

#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;
}
#包括
#包括
类SerializableFormat
{
公众:
尺寸i;
};
甲级
{
公众:
尺寸x,y;
A(大小n):x(n),y(1){
运算符常量SerializableFormat()常量
{
序列化格式结果;
结果:i=x;
如果(y)
{
结果:i/=y;
}
返回结果;
}
};
int main(int argc,const char*argv[]
{
std::向量v;
对于(大小i=0;i<20;i++)
{
v、 推回(A(i));
}
返回0;
}
  • 如果将Clang的编译标志设置为
    -std=c++98
    libstdc++
    ,则不存在任何问题,编译效果良好
  • 如果将Clang的编译标志设置为
    -std=c++11
    libc++
    ,我将得到错误
    从'A'到'value\u type'(也称为'SerializableFormat')没有可行的转换。
为了清楚起见--如果您正在考虑为类
a
提供SerializableFormat构造函数:

由于
SerializableFormat
类更适合于与各种类之间的转换,因此
A
(以及其他希望序列化的类)应该有构造函数和转换运算符,而不是期望
SerializableFormat
覆盖所有希望序列化的类,因此,修改
SerializableFormat
以拥有一个特殊的构造函数并不是一个解决方案


有人能看到我在这里做错了什么吗?

正如注释正确指出的那样,您可以通过在
SerializableFormat
转换运算符的返回类型中删除
const
进行编译:

运算符
常量
SerializableFormat()常量

至于clang的这种行为是否正确,这是一个有争议的问题。该问题正在由一位专家进行跟踪。目前有人在谈论创建一个CWG(C++委员会)问题报告,但这还没有完成。我注意到这个bug报告已经公开了一段时间(2013-07-23),但最近更新到2015-01-28


同时,实用的建议是永远不要按
const
-value返回。对于C++98/03来说,这是一个不错的建议,但对于移动语义来说,这是一个不好的建议,因为它将禁用移动语义。

对于GCC、libstdc++和
-std=C++11
,它仍然可以编译。转换运算符返回
const SerializableFormat
,没有意义——只需返回
SerializableFormat
,它也可以与clang一起工作——但我没有答案知道您的代码是否有效。我直到现在才注意到LLVM标记。最小测试用例:
struct A{};结构B{operator const A();};void f(){(A(B());}
在所有模式下都被GCC接受,只在C++03模式下发出叮当声。相关:为什么您首先会发现需要返回
const
对象?你在现场建造,没有必要保护它。如果返回引用,那将是另一回事。@markransem:C++98/03中有一条准则建议始终按
const
返回,以防止意外赋值给右值(如果右值是
const
,编译器会阻止它)。这条准则在Scott Meyers有效C++项目3中永存。