7

所以我有一个智能迭代器来模拟映射 const_iterator,它需要在内部构建返回类型。显然,我想将 a 存储pair<Key, Value>在我的迭代器类中(因为我需要修改它),但同时我希望取消引用函数呈现 a pair<const Key, Value>(实际上它分别是 aconst pair<const Key, Value>&const pair<const Key, Value>*)。到目前为止,我提出的唯一解决方案是每次更改我的迭代器类指向的值更改时动态分配一个新对。不用说,这不是一个好的解决方案。

我也试过*const_cast<const pair<const Key, Value> >(&value)wherevalue被声明为pair<Key, Value>.

任何帮助将不胜感激(正如无法做到的知识一样)。

编辑

对于好奇:我最终将 a 存储pair<const Key, Value> p在我的迭代器类中。为了更改对,我根据底层迭代器 ( map<Key, Value>::const_iterator it)分别更改两个元素,const_cast设置键以便可以更改它,如下所示:

*const_cast<Key*>(&p.first) = it->first;
p.second = it->second;

这不是我非常满意的解决方案,但它完成了工作,并且取消引用方法很高兴,因为我存储了正确类型的东西,它们可以引用。

4

5 回答 5

8

您可以将type的pair<Key,Value>转换为pair<const Key,Value>.

然而,仔细阅读这个问题,你实际上是在问,如果pair<Key,Value>你可以创建一个指针引用pair<const Key,Value>引用同一个对象。

答案是否定的——指向一种类型的引用或指针可以引用不同类型的对象的唯一情况是对象类型继承自被引用类型。

一种可能性是返回一对引用,pair<const Key&, Value&>,从您希望引用的对中创建。

于 2011-11-29T04:33:45.733 回答
5

是的。

std::pair<int, double> p(1,2);
std::pair<const int, double> q = p;   // no problem

//q.first = 8;  // error
q.second = 9;

int b; double d;
std::pair<int &, double &> s(b,d);
std::pair<int const &, double &> t = s;  // also fine
于 2011-11-29T04:26:39.380 回答
2

正如 Kerrek SB 指出的那样,您可以std::pair<const Key, Value>std::pair<Key, Value>. 但是,您最初的问题意味着您希望避免在每次取消引用迭代器时构造 std::pair 对象。

不幸的是,没有一个好的方法可以做到这一点。您可能必须构造对对象并将其实际存储在某个地方,特别是对于 operator->。否则,您必须能够让您的地图实际存储pair<const Key, Value>,以便能够从您的迭代器返回指向它的引用/指针。基本上要返回一个引用/指针,它必须以这种形式存储在某个地方:它不能是临时的。

避免使用 const_cast。这只是在您使用它以这种方式强制转换时要求未定义的行为,即使它可能经常工作。

于 2011-11-29T04:41:58.420 回答
1

这可以通过 来解决reinterpret_cast,它纯粹是一个编译时指令。

std::pair<int, double> p1 = { 1, 2.3 };
auto& p2 = reinterpret_cast<std::pair<const int, double>&>(p1);    // type of p2 is pair<const int, double>&

//++(p2.first);    // error: expression must be a modifiable lvalue
++(p1.first);
assert(p2.first == 2);


然而,reinterpret_cast这是一种危险的行为。我建议添加一个静态断言,以防止意外的部分模板专业化。

using srcType = std::pair<Key, Value>;
using tarType = std::pair<const Key, Value>;

static_assert(
    offsetof(srcType, first) == offsetof(tarType, first)
 && offsetof(srcType, second) == offsetof(tarType, second)
);
于 2020-10-17T07:02:48.360 回答
0

我遇到了完全相同的问题。我的解决方案是创建一个新的地图对象作为迭代器类的一部分,然后将上游地图类中缺少的成员添加到其中,并返回对其成员的引用。效率不高,但有效。

您的解决方案有两个问题:

  1. 使用 const_cast 分配 const 变量是未定义的行为。编译器优化可能会提供奇怪的结果。
  2. 任何新的取消引用都会使先前取消引用的结果无效。它不应该。因此,根据迭代器的使用情况,它也可能会产生奇怪的结果。
于 2015-10-27T13:02:31.130 回答