C++标准:多重集中出现意外的 const_iterator

发布于 2024-08-17 13:19:41 字数 1585 浏览 1 评论 0原文

我最近遇到了一个奇怪的问题,在迭代多重集时,我得到的是 const_iterator 而不是预期的 iterator。事实证明这对 MSVC 来说不是问题,但 g++ 给了我一个错误:

错误:无效的初始化 类型“myPtr&”的引用从 'const 类型的表达式 boost::shared_ptr'

相关代码:

typedef std::multiset<myPtr> myList;
myList _mystuff;
void tick(float dt)
{
    for (myList::iterator i = _mystuff.begin(); i != _mystuff.end(); ++i)
    {
        myPtr &mine = *i; // g++ problem here, not for MSVC
        // const myPtr &mine = *i; works fine for g++
        mine->tick(dt);
    }
}

相当多的研究表明这是一个之前讨论过的问题。我找到了这些相关位:

我对这个问题的背景知识和掌握是有限的因此我想知道标准是否没有足够好地定义这种行为,在这种情况下 g++ 和 MSVC 根据自己的喜好实现该行为,或者 g++ 或 MSVC 是否偏离了明确定义的标准。

提前致谢。

I recently ran into an odd issue where I'd get a const_iterator instead of the expected iterator when iterating through a multiset. It turned out to be a non-issue for MSVC but g++ gave me an error:

error: invalid initialization of
reference of type 'myPtr&' from
expression of type 'const
boost::shared_ptr'

Relevant code:

typedef std::multiset<myPtr> myList;
myList _mystuff;
void tick(float dt)
{
    for (myList::iterator i = _mystuff.begin(); i != _mystuff.end(); ++i)
    {
        myPtr &mine = *i; // g++ problem here, not for MSVC
        // const myPtr &mine = *i; works fine for g++
        mine->tick(dt);
    }
}

Quite a bit of research revealed that is a problem with lots of previous discussion. I found these relevant bits:

My background knowledge and grasp on the issue is limited and thus I'd like to know whether the standard doesn't define this behavior well enough in which case g++ and MSVC implement the behavior to their liking or whether either g++ or MSVC deviate from a well-defined standard.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧竹 2024-08-24 13:19:41

set 和 multiset 的迭代器从标准迭代器/const 迭代器对更改为 const 迭代器。进行此更改的原因是它们是有序容器,并且更改迭代器内部的元素实际上会使此排序约束无效。

您正在测试的 GCC 版本已进行此更改,而您正在使用的 VC 版本则没有。 VC10(我相信还有 VC9 SP1)总是从集合和多重集合返回 const_iterators。

C++1x 最新草案(目前为 n3000.pdf)的 23.2.4/6 说

对于关联容器,其中
值类型与键相同
类型,iterator 和 const_iterator
是常量迭代器。

std::set 和 std::multi_set 是关联容器,其中值类型与键类型相同。

The iterators for set and multiset were changed from the standard iterator/const iterator pair to just being const iterators. The reason for this change was that they are ordered containers, and changing the element inside of an iterator can actually invalidate this ordering constraint.

The version of GCC you're testing against has made this change, the version of VC that you're using has not. VC10 (and VC9 SP1, I believe) always return const_iterators from sets and multisets.

23.2.4/6 of the latest draft of C++1x (n3000.pdf at the moment) says

For associative containers where the
value type is the same as the key
type, both iterator and const_iterator
are constant iterators.

std::set and std::multi_set are the associative containers where the value type is the same as the key type.

巨坚强 2024-08-24 13:19:41

如何欺骗编译器 std::set::iterator?

我有一个结构,

struct _item {
  int a;
  int b;
  bool operator <(const _item& x) const {return a<x.a;}
};

我只想更改成员 b (b 与集合中的排序无关,仅比较成员 a)。

std::set<_item> data;
std::set<_item>::iterator iter=data.begin();
iter->b=0;  // error !!!

阿瓦达索命!

struct _item {
  int a;
  int b;
  _item* self;
  _item() {self=this;} 
  bool operator <(const _item& x) const {return a<x.a;}
};
iter->self->b=0; // Success !! Tested on VC10

当然C++更正确

struct _item {
  int a;
  int b;
 private:
  _item* self;
 public:
  _item() {self=this;} 
  bool operator <(const _item& x) const {return a<x.a;}
  int& bReference() const {return self->b;}
};
std::set<_item> items;
std::set<_item>::iterator iter=items.begin();
iter->bReference()=0; // Success !! Tested on VC1

How to fool the compiler for std::set::iterator?

I have struct

struct _item {
  int a;
  int b;
  bool operator <(const _item& x) const {return a<x.a;}
};

I want change only member b (b is irrelevant for sorting in set, only member a is compared).

std::set<_item> data;
std::set<_item>::iterator iter=data.begin();
iter->b=0;  // error !!!

Avada Kedavra !

struct _item {
  int a;
  int b;
  _item* self;
  _item() {self=this;} 
  bool operator <(const _item& x) const {return a<x.a;}
};
iter->self->b=0; // Success !! Tested on VC10

Of course more C + + correctly

struct _item {
  int a;
  int b;
 private:
  _item* self;
 public:
  _item() {self=this;} 
  bool operator <(const _item& x) const {return a<x.a;}
  int& bReference() const {return self->b;}
};
std::set<_item> items;
std::set<_item>::iterator iter=items.begin();
iter->bReference()=0; // Success !! Tested on VC1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文