gpt4 book ai didi

c++ - 如何编写可以采用 const 迭代器的 C++11 模板

转载 作者:IT老高 更新时间:2023-10-28 22:14:24 25 4
gpt4 key购买 nike

回复 this question在 CodeReview 上,我正在考虑如何编写模板函数来指示所包含对象的 const-ness。

具体来说,考虑这个模板化函数

#include <iostream>
#include <numeric>
#include <vector>

template <class It>
typename std::iterator_traits<It>::value_type average(It begin, It end) {
typedef typename std::iterator_traits<It>::value_type real;
real sum = real();
unsigned count = 0;
for ( ; begin != end; ++begin, ++count)
sum += *begin;
return sum/count;
}

int main()
{
std::vector<double> v(1000);
std::iota(v.begin(), v.end(), 42);
double avg = average(v.cbegin(), v.cend());
std::cout << "avg = " << avg << '\n';
}

它需要一个迭代器并根据包含的数字计算平均值,但保证不会通过传递的迭代器修改 vector 。如何将这一点传达给模板的用户?

注意,这样声明它:

template <class It>
typename std::iterator_traits<It>::value_type average(const It begin,
const It end)

不起作用,因为它不是迭代器,而是迭代器指向的东西,即const。我需要等待concepts标准化?

请注意,我不想要求 const 迭代器,而是表明它们可以 在这里安全使用。也就是说,我不想限制调用者,而是想传达我的代码正在做出的 promise :“我不会修改你的基础数据。”

最佳答案

template <class ConstIt>

就这么简单。在调用方这里没有什么要强制执行的,因为非 const 迭代器也可用于 const 访问,所以它只是 API 文档,这就是您的选择参数标识符是 - API 文档。

这确实导致了在被调用者/函数方面的强制执行问题 - 所以它不能假装它只会使用迭代器进行 const 访问然后无论如何都要修改元素。如果您关心这一点,您可以使用一些标识符来接受参数,以明确它并不打算在整个函数的任何地方使用,然后创建一个具有更方便标识符的 const_iterator 版本。这可能很棘手,因为通常您不知道迭代器类型是否是容器的成员,更不用说该容器类型是什么以及它是否也有 const_iterator,所以某种方式的概念确实是理想的——为 C++14 祈祷。同时:

  • 让您的来电者告诉您容器类型,
  • 写下你自己的特质,或者
  • 编写一个简单的包装类,它包含一个迭代器并确保只有 const 对引用数据的访问才能脱离接口(interface)

最后一种包装方法如下图所示(并非所有迭代器 API 都已实现,因此需要根据需要充实):

template <typename Iterator>
class const_iterator
{
public:
typedef Iterator iterator_type;
typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
// note: trying to add const to ...:reference or ..:pointer doesn't work,
// as it's like saying T* const rather than T const* aka const T*.
typedef const typename std::iterator_traits<Iterator>::value_type& reference;
typedef const typename std::iterator_traits<Iterator>::value_type* pointer;

const_iterator(const Iterator& i) : i_(i) { }
reference operator*() const { return *i_; }
pointer operator->() const { return i_; }
bool operator==(const const_iterator& rhs) const { return i_ == rhs.i_; }
bool operator!=(const const_iterator& rhs) const { return i_ != rhs.i_; }
const_iterator& operator++() { ++i_; return *this; }
const_iterator operator++(int) const { Iterator i = i_; ++i_; return i; }
private:
Iterator i_;
};

示例用法:

template <typename Const_Iterator>
void f(const Const_Iterator& b__, const Const_Iterator& e__)
{
const_iterator<Const_Iterator> b{b__}, e{e__}; // make a really-const iterator
// *b = 2; // if uncommented, compile-time error....
for ( ; b != e; ++b)
std::cout << *b << '\n';
}

查看 running at ideone.com here .

关于c++ - 如何编写可以采用 const 迭代器的 C++11 模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24675366/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com