【问题标题】:I can no longer assign char[M][N] types into a std::vector on gcc 4.9我不能再将 char[M][N] 类型分配给 gcc 4.9 上的 std::vector
【发布时间】:2024-04-16 01:25:02
【问题描述】:

在升级 Ubuntu 之前,我一直在使用 gcc 4.8,现在我有了 gcc-4.9.1-16。以前编译时没有警告并且运行良好的代码现在不再编译了。

static const unsigned WIDTH = 16;
static const unsigned VSCALE = 1;
static const unsigned HEIGHT = WIDTH / VSCALE;
static const unsigned FOOTER = 2;

typedef char Row [WIDTH + 1];
typedef Row World [HEIGHT - FOOTER];

std :: vector <World> m_levels;

World levels [] =
{
    {
        "                ",
        "                ",
        "                ",
        "                ",
        "                ",
        "  ###      ###  ",
        "                ",
        "1122112211221122",
        " 33003300330033 ",
        "1122112211221122",
        " 33003300330033 ",
        "                ",
        "                ",
        "                "
    },
    {
        "       44       ",
        "     555 55     ",
        "    66    66    ",
        "  777      777  ",
        " 66          66 ",
        "  777      777  ",
        "    66#  #66    ",
        "  777 #  # 777  ",
        " 66   #  #   66 ",
        "  777 #  # 777  ",
        "    66#  #66    ",
        "     555 55     ",
        "       44       ",
        "                "
    }
};

// The next line is line 68
m_levels .assign (std :: begin (levels), std :: end (levels));

最后一行错误

.../foo.cpp:68:62: 从这里需要 /usr/include/c++/4.9/bits/stl_algobase.h:373:4:错误:静态断言失败:类型不可分配

.../foo.cpp:68:62: 从这里需要 /usr/include/c++/4.9/bits/stl_construct.h:75:7:错误:数组新 [-fpermissive] 中带括号的初始化程序

编译选项没有改变,据我所知它们是-W -Wall -Wextra -Werror -pedantic --std=c++0x,只有 gcc 发生了变化。

为什么这段代码不再编译?

【问题讨论】:

    标签: c++ c++11 gcc


    【解决方案1】:

    标准容器的值类型的最低要求是它们必须是Erasable。对于默认分配器,这转换为给定value_type *p;p-&gt;~value_type(); 必须是格式良好的要求。

    如果value_type 是一个类类型,它只是调用析构函数,如果析构函数没有被删除并且是可访问的,则它是格式良好的。如果value_type 表示标量类型,则p-&gt;~value_type(); 也是有效的并且是无操作的(这称为伪析构函数调用)。但是,如果value_type是数组类型,那么p-&gt;~value_type();是无效的。

    因此,对于标准容器,内置数组永远不是有效的值类型,至少在使用默认分配器时是这样。 (各种其他容器操作对值类型提出了更多要求;内置数组至少会与其中一些发生冲突,因为它们不可赋值。)

    使用不满足该模板要求的类型来实例化标准库模板会导致未定义的行为。似乎 libstdc++ 碰巧直到 GCC 4.9 附带的版本才诊断出您的错误。

    顺便说一句,修复很简单。只需使用std::array

    【讨论】:

    • 我确信你所说的就规范而言是正确的,但我不明白为什么会这样。值类型的不可擦除性不只是根据指针操作定义可擦除性的任意结果吗?它似乎是语法而不是语义的约束。对吗?
    • 另外,如果数组不可赋值,the #if 1 version of this work 而不是#if 0 版本如何?
    • @spraff 嗯,是的,这是一个语法约束。他们本可以对标量类型的数组(以及标量类型的数组等)进行伪析构函数调用,但即便如此,它也不会很有用,因为数组是不可分配的(vector::assign() 显然需要),这反过来可以说是语法问题而不是语义......
    • @spraff 数组不可分配。包含数组的结构/类是。 std::array 只不过是一个内置数组的薄包装器。
    • 我在玩 std::array 但无法得到任何可以编译的东西。你的意思是什么简单的修复?非常感谢。
    【解决方案2】:

    过了一段时间,这个帖子帮我弄清楚了这个神秘的错误。我不得不使用的一些遗留代码也停止了编译,我不知道为什么。我没有注意到我在系统升级中更新了编译器版本,新标准导致

    stl_algobase.h:364:4: error: static assertion failed: type is not assignable

    我的解决方案是强制它使用 03 标准 (--std=c++03) 编译,而不是新的默认值。对于那些无法使用正确的std::array 重写大量代码的人,我将把它留在这里作为一个简单的解决方法。

    【讨论】:

      最近更新 更多