c++ - 与容器无关的迭代器参数

标签 c++ c++11 iterator

如何用 C++ 编写一个函数,以与容器无关的方式接收某种类型的迭代器作为参数?即

// C# version
void foo(IEnumerable<MyConcreteClass> t)
{
   foreach(MyConcreteClass c in t)
   {
     c.MyFunction();
   }
}

阅读有关迭代器的内容后,我似乎应该做这样的事情:

template<MyIter>
void foo(MyIter start, MyIter end, std::input_iterator_tag type)
{
  // How would the next part work?  Do I do:
  while (start != end)
  {
    MyConcreteClass* c = *start; // this will compile iff the parameter is correct.
    c->MyFunction();
    start++;
}

在传入无效迭代器类型的情况下(例如 std::unordered_set<MyOtherClass*>::iterator ),我认为使用此方法生成的编译器错误只是我取消引用 start 的行中的某种无效转换错误。 ;相反,我想得到一个错误,表明我实际上传递了错误类型的迭代器。有一个更好的方法吗?我很乐意说“MyIter 必须是来自 MyConcreteClass 容器的迭代器”

顺便说一句,C++11 机制没问题。

最佳答案

如果你愿意,你可以添加类似的内容

static_assert(std::is_convertible<decltype(*start), MyConcreteClass*>::value, "MyIter must be an iterator from a container of MyConcreteClass");

到函数体内的任何地方。

请注意,这与 MyConcreteClassfoo 紧密结合,因此,如果您确定需要这样做,那就没问题。但如果你不这样做,你可以对其进行更多的泛化并编写

template<MyIter>
void foo(MyIter start, MyIter end)
{
  while (start != end) {
    auto c = *start;
    c->MyFunction();
    // Or instead of the above two statements:
    // (*c)->MyFunction(); 
    start++;
  }
}

这适用于指向具有 MyFunction 函数的任何类型的指针,因此现在您甚至可以使用 unique_ptr 的容器,而以前则不能。但是,您无法轻松地为此编写断言语句,因此这是一种权衡。 C++ 的传统只是记录函数(例如,“此函数适用于在 operator-> 后面具有可用的 MyFunction() 的所有类型”)并让如果违反要求,编译器会出错。

关于c++ - 与容器无关的迭代器参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20308858/

相关文章:

c++ - 前增量和后增量

c++ - 显式默认模板化构造函数

c++ - 为链表返回正确类型的迭代器

c++ - 如果在我们插入数据库时​​电源关闭会发生什么?

c++ - 为什么需要多个shared_future对象来同步数据

c++ - decltype 和模板的问题

c++ - 在类外调用的私有(private)函数成员

Linux - 设置 Code::Blocks 来编译多线程 C++ 代码

c++ - 为什么 std::fill 使用 ForwardIterator 而不是 OutputIterator?

c++ - STL 迭代器 : container. 结束()