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

    只是为了说明清楚——如果您正在考虑为 SerializableFormat 提供一个仅用于 A 类的构造函数:

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

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

    最佳答案

    正如注释正确指出的那样,您可以通过在 const 转换运算符的返回类型中删除 SerializableFormat 来进行编译:
    operator const SerializableFormat() const
    至于 clang 这种行为是否正确,是有争议的。该问题正在由 clang bug report 16682 跟踪。目前有关于创建 CWG(C++ 委员会)问题报告的讨论,但尚未完成。我注意到这个错误报告已经开放了一段时间(2013-07-23),但最近在 2015-01-28 更新。

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

    关于C++11 与 C++98 转换运算符的行为发生了变化?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28510088/

  • 10-17 01:29