C++11 与 C++98 转换运算符行为发生变化?

C++11 vs C++98 conversion operator behavior changes?

我希望在一些现有的 c++ 项目中使用一些 c++11 功能,所以我开始在 Clang 中为一些项目更改编译标志,并且我将 运行 保留在有关 C+ 的特定问题中+11 对转换运算符(或转换运算符)的处理,我没想到会看到并且不明白为什么现在将其视为不是 c++11 的有效 C++ 代码时的错误

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

#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 提供一个仅用于 class A:

的构造函数

由于 SerializableFormat class 更适合与各种 class 进行相互转换,因此对于 A(以及其他 class希望序列化的 es) 拥有构造函数和转换运算符,而不是期望 SerializableFormat 涵盖想要序列化的每种类型的 class,因此修改 SerializableFormat 以具有特殊的构造函数是不是解决方案。

谁能看出我做错了什么?

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

operator const SerializableFormat() const

至于clang这种行为是否正确,是有争议的。 clang bug report 16682 正在跟踪此问题。目前正在谈论创建 CWG(C++ 委员会)问题报告,但尚未完成。我注意到此错误报告已经开放了一段时间 (2013-07-23),但最近更新于 2015-01-28。

同时,切合实际的建议是永远不要将 return 提高 const 值。这对 C++98/03 来说是个不错的建议,但是移动语义变成了糟糕的建议,因为它会禁用移动语义。