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


我希望在一些现有的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;
}
  • 如果Clang的编译标志设置为 -std=c++98 和 libstdc++,没有问题,这编译好。
  • 如果Clang的编译标志设置为 -std=c++11 和 libc++,我收到错误 No viable conversion from 'A' to 'value_type' (aka 'SerializableFormat')

只是为了清楚 - 如果你正在考虑为SerializableFormat提供一个仅用于类的构造函数 A

自从 SerializableFormat class更适合转换到各种类,从而有意义 A (以及其他希望可序列化的类)具有构造函数和转换运算符而不是期望 SerializableFormat 覆盖每个想要序列化的类,所以修改 SerializableFormat 拥有一个特殊的构造函数不是一个解决方案。

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


4114
2018-02-13 22:50


起源

使用GCC,libstdc ++和 -std=c++11,它仍然编译。转换运算符返回没有任何意义 const SerializableFormat  - 回来吧 SerializableFormat 相反,它也适用于clang - 但我没有答案你的代码是否有效。
直到现在我才注意到LLVM标签。这会改变一切。 - Austin Mullins
最小的测试用例: struct A { }; struct B { operator const A(); }; void f() { (A(B())); } GCC在所有模式下都被GCC接受,只能在C ++ 03模式下进行。
有关: stackoverflow.com/q/16834937/819272 - TemplateRex


答案:


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

operator  const  SerializableFormat() const

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

与此同时,实际建议永远不会回归 const-值。对于C ++ 98/03来说,这是一个不错的建议,但是移动语义变成了糟糕的建议,因为它会禁用移动语义。


13
2018-02-13 23:50



你为什么觉得有必要退回一个 const 对象首先?你现场正在建造它,没有必要保护它。如果你要回来了 参考 那将是另一回事。 - Mark Ransom
@MarkRansom:在C ++ 98/03中,建议总是返回一个指南 const 防止意外分配到右值(如果右值是,编译器会阻止它) const)。该指南在Scott Meyers Effective C ++ Item 3中永生。 - Howard Hinnant