c++ 中带有容器迭代器的循环类型依赖关系(GCC 失败,而 MSVC 正常)
Circular type dependency in c++ with container iterators (GCC fails, while MSVC ok)
我编写的原始代码在Microsoft的编译器上开箱即用,但不能使用gcc(4.7.4(编译:以下是简化的代码:
// test.cpp
#include <unordered_map>
using namespace std;
struct order_rec;
typedef unordered_map<int, order_rec> placed_orders_t;
typedef placed_orders_t::iterator placed_order_iterator;
typedef unordered_map<int, placed_order_iterator> book_list_t;
typedef book_list_t::iterator book_list_iterator;
struct order_rec
{
int a;
book_list_iterator bi;
};
int main()
{
book_list_t test1;
order_rec test2;
}
G++不喜欢这一行:typedef placed_orders_t::iterator placed_order_iterator;
,它出错了,因为该行struct order_rec
没有完全声明。
如您所见,我有一个 int => order_rec 的地图placed_orders_t
,然后我有另一个地图book_list_t
将 int 映射到迭代器到placed_orders_t
地图中。然后,order_rec本身将交互器存储到book_list_t
映射中。
请注意,我相信这是 gcc 实现 unordered_map(或者编译器本身(中的一个错误:如果我将 typedef placed_orders_t
作为 std::map,那么一切都可以正常编译;但是,我确实需要在那里使用无序映射。
什么可以用作解决方法?
这是 g++ 编译的相关部分
g++-4.7 -O3 -DNDEBUG -std=c++11 -c test.cpp
...
/usr/include/c++/4.7/bits/unordered_map.h:264:11: required from ‘class std::unordered_map<int, order_rec>’
test.cpp:7:24: required from here
/usr/include/c++/4.7/bits/stl_pair.h:94:11: error: ‘std::pair<_T1, _T2>::second’ has incomplete type
test.cpp:5:8: error: forward declaration of ‘struct order_rec’
您拥有的代码是未定义的行为。当你写:
struct order_rec;
typedef unordered_map<int, order_rec> placed_orders_t;
typedef placed_orders_t::iterator placed_order_iterator;
这需要实例化placed_orders_t
,这需要实例化unordered_map<int, order_rec>
。 在这一点上,order_rec
是不完整的。从 [res.on.functions]:
特别是,在以下情况下,效果是未定义的:[...]如果在实例化模板组件时将不完整的类型(3.9(用作模板参数,除非该组件特别允许。
标准库中的某些类模板允许不完整的类型(如 unique_ptr
或 vector
(,但unordered_map
不是其中之一,因此其效果是未定义的。编译失败是允许的效果。请注意,map
也是如此,即使您的代码可以编译。
您必须placed_orders_t::mapped_type
是可以在此上下文中使用的类型。也许std::unique_ptr<order_rec>
?
不是一个很好的解决方案,但我们可以更改order_rec
并尽早声明它。
struct book_list_iterator;
struct order_rec
{
int a;
vector <book_list_iterator> bi;
};
这是有效的vector
因为它显式允许不完整的类型作为成员类型。
(我确实考虑过shared_ptr
和unique_ptr
而不是vector
,但我认为这是避免为order_rec编写复制构造函数的最简单方法(
要访问单个迭代器,我们需要->bi.at(0)
,而不仅仅是->bi
。
最后,book_list_iterator
不是typedef,而是一个结构体
typedef unordered_map<int, order_rec> placed_orders_t;
typedef placed_orders_t::iterator placed_order_iterator;
typedef unordered_map<int, placed_order_iterator> book_list_t;
struct book_list_iterator : public book_list_t::iterator
{
};
我认为这是一个编译器问题。但通常它不应该工作,因为当您使用typedef unordered_map<int, order_rec> placed_orders_t;
时,它需要知道order_rec
的大小,以便它可以相应地分配内存,这在您的情况下是未知的,因此要么使用 order_rec*
代替order_rec
,要么在使用之前将struct order_rec
的定义移动到它。
- gcc和c++17的过载解析失败
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 自定义对象的dlib序列化在gcc中失败
- GCC 4.8.2 自动矢量化由于 cout 而失败
- 调试模板时出现问题.专门针对 Linux GCC 7、GCC 6、GCC 5、GCC 4.9 错误构建失败:模板参数 1
- C++正则表达式失败(GCC vs Microsoft 编译器)
- 带有引用的std::tuple在clang中编译失败,但在gcc中编译失败
- thread_local静态成员模板定义:初始化失败,GCC
- C++指向成员的指针的类内初始化会使 MSVC 失败(但 GCC/Clang 工作)
- 在 GCC 中工作的外行构造函数模板在 Clang 中失败
- enable_if is_same constexpr函数使MSVC失败(但在Clang,GCC中效果很好)
- GCC 模板参数推断/替换失败
- 为什么这段代码在Visual Studio中有效,但在gcc中失败
- 为什么将 lambda 用于非类型模板参数时 gcc 失败?
- 匿名结构可提高函数转换在GCC 5.4上失败
- 线性重载:为什么 clang 在 GCC 编译时失败?
- enable_if的模板专用化在 Clang 中失败,适用于 GCC
- 继承默认构造函数在 gcc 中失败并在 clang 中工作,哪个有错误?
- 为什么GCC中std::set的推导失败
- 为什么结构化绑定在 GCC 上失败