C++ 11与C++ 98转换运算符的行为有何变化?

tjg*_*ant 11 c++ llvm libstdc++ c++11 libc++

我希望在一些现有的c ++项目中使用一些c ++ 11特性,所以我开始在一些项目中更改Clang中的编译标志,并且我一直在遇到关于C++ 11处理转换操作符(或者转换)的特定问题运算符)我没想到会看到并且不明白为什么现在这被认为是一个错误,因为它是有效的C++代码而不是c ++ 11

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

#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;
}
Run Code Online (Sandbox Code Playgroud)
  • 如果Clang的编译标志设置为-std=c++98libstdc++,则没有问题,这可以很好地编译.
  • 如果Clang的编译标志设置为-std=c++11libc++,我得到错误No viable conversion from 'A' to 'value_type' (aka 'SerializableFormat')

只是为了清楚 - 如果你正在考虑给SerializableFormat一个只为该类的构造函数A:

由于SerializableFormat该类更适合于从各种类转换,因此A(和其他希望可序列化的类)使用构造函数和转换运算符而不是期望SerializableFormat涵盖想要可序列化的所有类的类是有意义的,所以修改SerializableFormat为具有特殊构造函数不是解决方案.

谁能看到我在这里做错了什么?

How*_*ant 13

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

operator const SerializableFormat() const

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

与此同时,实用建议永远不会以价值回报const.这对于C++ 98/03来说是不错的建议,但是移动语义会变成糟糕的建议,因为它会禁用移动语义.

  • @MarkRansom:在C++ 98/03中,建议总是通过`const`返回以防止意外赋值给rvalue(如果rvalue是`const`,编译器会阻止它).该指南在Scott Meyers Effective C++ Item 3中永生不朽. (6认同)
  • 为什么你首先会发现有必要返回一个 `const` 对象?你在现场建造它,没有必要保护它。如果您要返回 *reference*,那将是另一回事。 (2认同)