是std :: map :: iterator实例化std :: map ?

问题描述 投票:15回答:2

我有这个代码,适用于GCC:

#include <map>

class Foo;
class Bar;

typedef std::map<Foo,Bar> MyMap;

MyMap::iterator i;

class Foo
{
    MyMap::iterator some_data;
};

目前设计的代码(这是令人不快的循环是的,我坚持使用它)需要map<Foo,Bar>::iterator可用于FooBar

它的工作原理是因为GCC库实现不需要实例化映射的键类型以实例化迭代器。

这有保证吗?在定义map迭代器类型时,标准似乎有点不干涉。这段代码有多便携?

c++ templates iterator stdmap c++-standard-library
2个回答
3
投票

这导致未定义的行为。

在声明MyMap::iterator i;中,MyMap必须是一个完整的类型,因此它是隐式实例化的。但是,FooBar在实例化的这一点上并不完整,所以根据[res.on.functions]/2的行为是不确定的:

特别是,在以下情况下,效果未定义:

  • ...
  • 如果在实例化模板组件或评估概念时将不完整类型([basic.types])用作模板参数,除非特别允许该组件。

0
投票

您可以通过考虑std::map是基于节点的容器这一事实来支持整个问题,以便其包含元素的节点具有稳定的地址。即您可以使用普通指针而不是迭代器(当然,只要您不需要迭代器传递到std::map的成员函数):

class Foo
{
    std::pair<Foo const, Bar>* some_data;
};

请注意,此处仅需要声明FooBarstd::pair<>来定义成员some_data

如果你使用boost::multi_index(它在很多方面优于std关联容器)那么它有非常有用的函数to_iterator,它接受对元素的引用并返回一个迭代器。

© www.soinside.com 2019 - 2024. All rights reserved.