【问题标题】:Specialize std::copy for custom iterators为自定义迭代器专门化 std::copy
【发布时间】:2019-04-18 13:17:45
【问题描述】:

据我了解,可以write template specializations 用于 std 命名空间中的函数模板。我写了一个CircularBuffer<T> 类并为这个类实现了一个随机访问迭代器。 std::copy() 算法也适用于我的自定义迭代器,但它不是最优的。它遍历范围并一一复制元素。通过在内部指针上使用std::memcpy(),我可以为可复制的类型编写更优化的实现。

我的问题是这甚至可能吗?我知道如何创建std::copy() 的重载作为模板,输出迭代器是模板参数。但这无法做到,因为您只能在 std 命名空间中编写函数模板的模板特化。任何有助于为我指明正确方向的帮助都会有所帮助。从我可以通过 Google 收集到的信息来看,这是无法做到的,但我很想被证明是错误的 :)

【问题讨论】:

  • 看来CircularBuffer是模板,我们不能部分特化函数,所以唯一的解决办法就是重载……但是不能在命名空间std中添加。
  • 我不会写任何函数specializations in new code
  • @StoryTeller 它还声明只要涉及至少一种程序定义的类型就可以了。
  • @darune - 它还说 C++20 取消了对函数模板的允许,使其仅适用于 类模板
  • 澄清一下:您的CircularBuffer::iterator 是RandomAccessIterator 但不是ContiguousIterator,但是有连续的部分,类似于std::deque

标签: c++ iterator template-specialization


【解决方案1】:

也许你的问题应该是:我应该这样做吗?

使用您的类的用户应该已经知道std::copy 是什么以及它是如何工作的以及内在的性能影响。因此,提供专业化可能会使事情变得更糟。 std::copy 保证进行了 N 个分配;根据the standard

正是(last - first) 分配

此外,在使用std::copy 时,它也与back_inserters 或其他操纵器一起使用并不少见,这可能无法很好地进行优化。

但是,例如,您可以选择提供对缓冲区的直接访问,例如 std::vector::data

我的问题是这可能吗?

您似乎拥有的解决此问题的一种方法是将这些知识(在某种意义上)输出给您班级的用户。只需添加一个额外的间接级别。因此,不是直接对元素使用迭代器,而是将迭代器返回到内存块。然后您将能够拥有连续的迭代器。

https://en.cppreference.com/w/cpp/named_req/ContiguousIterator

【讨论】:

  • 据我了解,使用std::copy() on std::vector<int> invokes std::memcpy() or std::memmove()。你是说这是不正确的行为吗?
  • @rozina 因为对于ints,memcpy 与赋值没有区别,'as-if 规则'允许编译器使用一个而不是另一个。
  • 我想将std::copy 专门用于我的CircularBuffer&lt;int&gt;。我在我的问题中已将其作为可复制的类型。所以希望这能回答你的问题,我应该为 std::copy 编写优化。
  • @rozina 它基于我所看到的迭代器属性。你有比std::vector 更类似于std::deque 的东西。因此,如果这对您的课程至关重要-那么我想您只能将这些知识导出给用户,以便您的迭代器可以在类型上变得连续;见en.cppreference.com/w/cpp/named_req/ContiguousIterator
  • 我看不到我的迭代器如何成为 ContiguousIterators,因为两个迭代器表示的范围在内存中并不连续。但是我有一个从CircularBuffer 复制数据的算法,它最多使用2 次std::copy() 调用,整数转换为std::memcpy()。如果std::copy() 能以某种方式使用我的算法而不是它自己的算法,我会很高兴。但由于我不应该超载std::copy(),我的问题是,如果这可能以及如何实现。
猜你喜欢
  • 2020-02-13
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多