有没有标准的 C++相当于 IEnumerable在 C# 中?
或者,如果 T 的枚举器只是列出所有元素,那么使用向量是否安全?
Or is it safe to use vector if the Enumerator of T is just listing all the elements?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C++ 中不需要它,原因如下:
C# 仅支持动态多态性。因此,要创建可重用的算法,您需要一个所有迭代器都将实现的接口。这就是
IEnumerator
,而IEnumerable
是一个用于返回迭代器的工厂。另一方面,C++ 模板支持鸭子类型。这意味着您不需要通过接口约束泛型类型参数来访问成员 - 编译器将按模板的每个单独实例化的名称查找成员。
C++ 容器和迭代器具有隐式接口,相当于 .NET,即:
IEnumerable
、IEnumerator
、ICollection
、< code>IList对于容器:
iterator
和const_iterator
typedefbegin()
成员函数 - 满足IEnumerable::GetEnumerator()
end()
成员函数的需求 - 而不是IEnumerator::MoveNext()
返回值对于前向迭代器:
value_type
typedefoperator++
-- 而不是IEnumerator::MoveNext()
operator*
和operator->
-- 而不是IEnumerator:: 来自
operator*
的当前IList
索引器设置器operator==
和operator!=
-- 在 .NET 中没有真正的等效项,但容器的end()
与IEnumerator::MoveNext()
返回匹配value对于随机访问迭代器:
operator+
、operator-
、operator[]
- 而不是IList
如果你定义这些,那么标准算法将适用于您的容器和迭代器。不需要接口,不需要虚拟功能。不使用虚函数使得 C++ 泛型代码比等效的 .NET 代码更快,有时甚至快得多。
注意:在编写通用算法时,最好使用
std::begin(container)
和std::end(container)
而不是容器成员函数。这允许您的算法除了 STL 容器之外还可以与原始数组(没有成员函数)一起使用。原始数组和原始指针满足容器和迭代器的所有其他要求,但只有一个例外。It isn't needed in C++, and here's why:
C# only supports dynamic polymorphism. So to create a reusable algorithm, you need an interface which all iterators will implement. That's
IEnumerator<T>
, andIEnumerable<T>
is a factory for returning an iterator.C++ templates, on the other hand, support duck typing. That means you don't need to constrain a generic type parameter by an interface in order to access members -- the compiler will look up members by name for each individual instantiation of the template.
C++ containers and iterators have implicit interfaces which is equivalent to .NET
IEnumerable<T>
,IEnumerator<T>
,ICollection<T>
,IList<T>
, namely:For containers:
iterator
andconst_iterator
typedefsbegin()
member function -- fills the need forIEnumerable<T>::GetEnumerator()
end()
member function -- instead ofIEnumerator<T>::MoveNext()
return valueFor forward iterators:
value_type
typedefoperator++
-- instead ofIEnumerator<T>::MoveNext()
operator*
andoperator->
-- instead ofIEnumerator<T>::Current
operator*
-- instead ofIList<T>
indexer setteroperator==
andoperator!=
-- no true equivalent in .NET, but with container'send()
matchesIEnumerator<T>::MoveNext()
return valueFor random access iterators:
operator+
,operator-
,operator[]
-- instead ofIList<T>
If you define these, then standard algorithms will work with your container and iterator. No interface is needed, no virtual functions are needed. Not using virtual functions makes C++ generic code faster than equivalent .NET code, sometimes much faster.
Note: when writing generic algorithms, it's best to use
std::begin(container)
andstd::end(container)
instead of the container member functions. That allows your algorithm to be used with raw arrays (which don't have member functions) in addition to the STL containers. Raw arrays and raw pointers satisfy all other requirements of containers and iterators, with this single exception.如果我们严格地坚持这个问题,据我所知,答案是否定的。人们一直在回复 C++ 中可用的替代品是什么,这可能是很好的信息,但不是答案,而且 OP 很可能已经知道了。
我完全不同意“不需要”,只是C++和.NET标准库的设计不同。 IEnumerable<>的主要特点是它是多态的,因此它使调用者能够使用他想要的任何类(数组、列表、集合等),同时仍然提供编译时强类型,即使在库 API 中也能实现故障安全。
C++ 中唯一的替代方案是模板。但 C++ 模板不是安全类型的运行时泛型,它们基本上是一种宏。因此,首先使用 C++ 中的模板,您必须向需要使用您的模板的任何人提供整个模板源代码。此外,如果您将库 API 模板化,您将无法保证对它的调用能够编译,并且代码不会自动自记录。
我完全同情任何其他同时使用 C# 和 C++ 的程序员,并对这一点感到沮丧。
然而,C++2X 计划添加包括范围在内的功能(这可能满足 OP?);以及概念(解决了模板的弱/坏类型检查问题 - Bjarne Stroustrup 承认的缺陷 他自己)和模块(这可能会或可能不会帮助减少仅标题模板的痛苦)。
If we stick to the question strictly the answer is no, as far as I know. People have kept replying what is the substitute available in C++, which may be good info but not answers, and which the OP most probably knew already.
I completely disagree that "it is not needed," it is just that the designs of the C++ and .NET standard libraries are different. The main feature of IEnumerable<> is that it's polymorphic, and so it enables the caller to use whatever class he wants (array, List, Set etc.), while still providing compile-time strong typing, fail-safe even in library APIs.
The only alternative in C++ is templates. But C++ templates are not safely typed run-time generics, they are basically kind of macros. So first of all with templates in C++ you are forced to provide the whole template source code to whoever needs to use your template. Moreover if you make your library API templated you lose the ability to guarantee that a call to it will compile, and the code is not automatically self-documenting.
I fully sympathize with any other programmer who uses both C# and C++ and is frustrated with this point.
However C++2X is planned to add features including ranges (which may satisfy the OP?); as well as concepts (which address the weak/bad type-checking of templates -- flaw admitted by Bjarne Stroustrup himself), and modules (which may or may not help reducing the pain from header-only templates).
标准 C++ 方法是传递两个迭代器:
客户端代码示例:
通用编程!
The standard C++ way is to pass two iterators:
Example client code:
Yay generic programming!
IEnumerable
在概念上与vector
非常不同。IEnumerable
提供对对象序列的只进、只读访问,无论什么容器(如果有)保存对象。向量
实际上是一个容器本身。在 C++ 中,如果您想要提供对容器的访问而不提供该容器的详细信息,则约定是传入两个代表容器开始和结束的迭代器。
一个很好的例子是 accumulate 的 C++ STL 定义,它可以与 < a href="http://msdn.microsoft.com/en-us/library/bb548651.aspx" rel="noreferrer">IEnumerable.Aggregate
在 C++ 中
在 C# 中
IEnumerable<T>
is conceptually very different fromvector
.The
IEnumerable
provides forward-only, read-only access to a sequence of objects, regardless of what container (if any) holds the objects. Avector
is actually a container itself.In C++, should you want to provide access to a container without giving the details of this container, the convention is to pass in two iterators representing the beginning and end of the container.
A good example is the C++ STL definition of accumulate, which can be contrasted with IEnumerable<T>.Aggregate
In C++
In C#