【问题标题】:getting a const_iterator from iterator [duplicate]从迭代器获取 const_iterator [重复]
【发布时间】:2011-09-28 23:18:42
【问题描述】:

可能重复:
Obtaining const_iterator from iterator

我想写一个从iterator返回对应const_iterator的元函数

template <class Iterator>
struct get_const_iterator
{
    typedef ??? type;
};
  • get_const_iterator&lt;int*&gt;::type 必须是 const int*
  • get_const_iterator&lt;const int*&gt;::type 必须是 const int*
  • get_const_iterator&lt;int* const&gt;::type 必须是 const int* 或 const int* const,我不在乎
  • get_const_iterator&lt;std::list&lt;char&gt;::iterator&gt;::type 必须是 std::list&lt;char&gt;::const_iterator

等等

可以使用iterator_traits 还是不使用它们?

编辑: 假设如果 2 个容器具有相同的 iterator 类型,那么它们也具有相同的 const_iterator 类型。我认为这是一个合理的假设,尽管理论上并不完全正确。

【问题讨论】:

  • 我认为您要求的通信没有明确定义。原则上,虽然这将是一个奇怪的实现,vector&lt;int&gt;::iterator 和 list&lt;int&gt;::iterator 可以是同一个类(不符合单一责任原则的情况如何?),但 vector&lt;int&gt;::const_iterator 和 list&lt;int&gt;::const_iterator 可以是不同的类。跨度>
  • @Fred: 嗯.. 可能的骗子问是否有一个,而不是如何写一个:)
  • @Armen:实际问题是否可以通过驱动底层迭代器并构造对元素的所有引用的包装器来解决,而不是告诉您任何特定容器使用的实际类型作为其const_iterator ?实际上有几个包装器,因为您想在迭代器标签上进行调度。

标签: c++ templates stl iterator template-meta-programming


【解决方案1】:

如果您愿意部分专门化容器,您可以在当前标准中执行此操作,例如...

#include <vector>
#include <list>
#include <iterator>

// default case
template <typename Iterator, typename value_type, typename container_test = Iterator>
struct container
{
  typedef Iterator result;
};

// partial specialization for vector
template <typename Iterator, typename value_type>
struct container<Iterator, value_type, typename std::vector<value_type>::iterator>
{
  typedef typename std::vector<value_type>::const_iterator result;
};

// partial specialization for list, uncomment to see the code below generate a compile error
/* template <typename Iterator, typename value_type>
struct container<Iterator, value_type, typename std::list<value_type>::iterator>
{
  typedef typename std::list<value_type>::const_iterator result;
}; */

// etc.

template <typename Iterator>
struct get_const
{
  typedef typename container<Iterator, typename std::iterator_traits<Iterator>::value_type>::result type;
};

int main(void)
{
  std::list<int> b;
  b.push_back(1);
  b.push_back(2);
  b.push_back(3);
  get_const<std::list<int>::iterator>::type it1 = b.begin(), end1 = b.end();
  for(; it1 != end1; ++it1)
    ++*it1; // this will be okay

  std::vector<int> f;
  f.push_back(1);
  f.push_back(2);
  f.push_back(3);

  get_const<std::vector<int>::iterator>::type it = f.begin(), end = f.end();
  for(; it != end; ++it)
    ++*it; // this will cause compile error

}

当然,会重复上面史蒂夫的观点,并且要求您的迭代器存在iterator_traits。

【讨论】:

  • 需要对每种容器类型进行专门化,因此例如对于用户容器将停止工作。
【解决方案2】:

你可以在 C++0x 中做到这一点

template <typename Container>
Container container (typename Container :: iterator);

template <typemame Iterator>
struct get_const_iterator
{
    typedef decltype (container (Iterator())) :: const_iterator type;
};

虽然我开始同意 Steve 的观点——这不是一个通用的解决方案,因为不同的容器可能具有相同的迭代器类型。

【讨论】:

  • 我认为史蒂夫的评论在这里很中肯。
  • @Armen:在他们尝试之前将人类送入太空是科幻小说......然后火箭爆炸了,因为有人犯了编程错误。
  • 另外,这仅满足@Armen 的最后一个要求。
  • 看起来很合理,但我认为它不需要我的科幻场景出错。如果多个容器共享一个迭代器,那么对container 的调用不是模棱两可吗,即使这些容器实际上也都使用相同的 const_iterator?多个容器共享一个迭代器实际上并不是那么不可信——例如,如果vector&lt;int&gt; 和array&lt;int&gt; 都使用int*(或相同的辅助类)。不太可能的是,他们不会分享const_iterator。
  • @Martinho:公平地说,它尝试的部分是棘手的部分。从过去的问题来看,我认为 Armen 可能已经将他的结构部分专门用于指针类型:-)
猜你喜欢
  • 2011-07-03
  • 2021-01-15
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
  • 2020-12-22
  • 2021-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多