是否可以将一对<key,value =“”>转换为一对<const key,=“”value =“”>?</const> </key,>

时间:2011-11-29 04:18:57

标签: c++ stl const const-cast std-pair

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

我还尝试了*const_cast<const pair<const Key, Value> >(&value),其中value被声明为pair<Key, Value>

任何帮助都会受到高度赞赏(因为知道它无法完成)。

修改

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

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

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

5 个答案:

答案 0 :(得分:8)

您可以将pair<Key,Value>类型的转换为pair<const Key,Value>

但是,仔细阅读问题,您实际上是在询问pair<Key,Value>是否可以创建指针引用pair<const Key,Value>引用同一个对象。

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

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

答案 1 :(得分: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

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:0)

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

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

  1. 使用const_cast分配const变量是未定义的行为。编译器优化可能会产生奇怪的结果。
  2. 任何新的取消引用都会使之前取消引用的结果无效。它不应该。因此,根据迭代器的用法,它也可能产生奇怪的结果。

答案 4 :(得分:0)

这可以通过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);
cout << p2.first;    // result is 2