【问题标题】:STL container holding class within declaration of that classSTL 容器在该类的声明中持有该类
【发布时间】:2016-05-12 20:51:20
【问题描述】:

我用 C++ 编写了一个程序,它可以用 clang++ 编译,但不能用 g++ 编译,我想了解原因。

关键部分是这样的:

class Table {
    private:
        ...
        std::unordered_map<std::string,Table> table_map;
        ...
};

我认为 std::unordered_map 会“在后台”使用指针,所以这是合法的。我不是在表内声明表,而是在创建一个容器,该容器具有指向表内表的指针。或者我是这么想的。 Clang++对此没有任何问题,程序运行良好。

但是,g++ 对此表示抱怨,说“note: forward declaration of 'class Table'”。这表明我应该明确地让 std::unordered_map 接受一个指针(std::unordered_map&lt;std::string,Table*&gt;,或者可能是某种智能指针)。这需要我做一些额外的工作(而且我正在处理我一年多前编写的代码,所以我并不急于必须弄清楚我做了什么才能进行必要的更改)。

这是 g++ 中的一个错误,还是 clang++ 做了一些不属于标准的聪明事情?有没有更好的方法来重写这段代码,以便在 clang++ 和 g++ 上编译?

我有另一个名为 Value 的类,并且 Table 中有一个值的 std::unordered_map,所以我是否可以通过创建一个超类 Element 来解决这个问题,Value 和 Table 都从该元素继承,然后让 Table 包含一个 @987654324 @?或者这样的地图会因为它是为元素声明的而无法存储值和表吗?

【问题讨论】:

  • 计划std::vector, std::list, and std::forward_list` 支持不完整的类型,但还没有std::unordered_map。也许 Boost 的地图支持它。

标签: c++ pointers c++11 stl


【解决方案1】:

该错误是由 std::unordered_map 必须重新散列表然后复制元素引起的。因此,容器中存储的值必须是完整类型。

您可以通过将值包装到智能指针中来克服它:

#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>           // shared_ptr

class Table {
    private:
    std::unordered_map<std::string, std::shared_ptr<Table> > t;
};

int main() {
    Table t;
    return 0;
}

Compiles.

【讨论】:

    【解决方案2】:

    这是未定义的行为。标准库容器不能用不完整的类型实例化,除非它明确说明容器支持它(例如unique_ptr)。

    您的选择是:

    • 重新设计你的代码不要这样做
    • 使用支持此功能的容器库

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-29
      • 1970-01-01
      • 2023-03-16
      相关资源
      最近更新 更多