C++ 17引入了ContiguousIterator的概念http://en.cppreference.com/w/cpp/iterator.然而,似乎没有计划contiguous_iterator_tag(通过我们现在以同样的方式random_access_iterator_tag)报告std::iterator_traits<It>::iterator_category.
为什么contiguous_iterator_tag失踪?
是否有传统的协议来确定迭代器是否是连续的?还是编译时间测试?
在过去我提到过,对于容器,如果有一个.data()成员转换为指向::value类型的指针,并且有.size()成员可转换为指针差异,那么应该假设容器是连续的,但我不能提取迭代器的类似特征.
一种解决方案可能是data为连续迭代器提供一个函数.
当然,连续概念&(it[n]) == (&(*it)) + n在所有情况下都有效n,但在编译时无法检查.
编辑:我发现这个视频把它放在更广泛的C++概念上下文中.CppCon 2016:"在现代多核世界中构建和扩展迭代器层次结构",作者:Patrick Niedzielski.解决方案使用概念(Lite),但最后的想法是连续的迭代器应该实现一个pointer_from函数(与我的data(...)函数相同).
结论是概念将有助于形式化理论,但它们并不神奇,在某种意义上,某个人会在某个地方定义新的特别命名的函数而不是连续的迭代器.这个讨论概括了分段迭代器(带有相应的函数segment和local),不幸的是它没有说明跨步指针.
我是C++的新手,所以请耐心等待.我想了解STL iterator_traits.在"C++标准库"一书中,iterator_traits结构定义如下:
template <class T>
struct iterator_traits{
typedef typename T::value_type value_type
typedef typename T::difference_type difference_type
typedef typename T::iterator_category iterator_category
typedef typename T::pointer pointer
typedef typename T::reference reference
}
Run Code Online (Sandbox Code Playgroud)
所以在我看来,它正在重新暴露T已经暴露的子类型.继续前进,本书给出了如何使用它的示例,如下所示
template <class MyIterator>
void do_something(MyIterator start, MyIterator end) {
typedef typename iterator_traits<MyIterator>::value_type value_type
value_type v = *start
.....
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么我在这里需要这个iterator_traits结构,如果想要获得它value_type,我不能MyIterator直接获得它吗?我的困惑似乎来自于我(肯定是不正确的)理解,即子类型的信息必须来源于template <class T>用于实例化iterator_trait.所以如果你能解释一下,最好用一个例子说明为什么以及在哪里我需要iterator_traits,这将是非常有帮助的.
在我的项目中,我想将流分割为某些给定类型的值,因此我将模板函数实现为
template <typename TElem, typename TOutputIter>
TOutputIter SplitSpace(std::istream& IS, TOutputIter result)
{
TElem elem;
while (IS >> elem)
{
*result = elem;
++result;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我认为这很尴尬,因为我必须明确给出TElem调用时的类型.例如,我必须写:
std::vector<int> v;
SplitSpace<int>(std::cin, back_inserter(v));
// I want to it to be SplitSpace(std::cin, back_inserter(v));
Run Code Online (Sandbox Code Playgroud)
我试图从(模板)迭代器获取值类型并使用std::iterator_traits如下:
template <typename TOutputIter>
TOutputIter SplitSpace(std::istream& IS, TOutputIter result)
{
typename std::iterator_traits<TOutputIter>::value_type elem;
while (IS >> elem)
{
*result = elem;
++result;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
但是,上述代码不起作用back_insert_iterator.我检查的源代码back_insert_iterator/front_insert_iterator/insert_iterator中std的命名空间,发现value_type/difference_type/pointer/reference都是 …
为何选择STL
std::iterator_traits<const T*>::value_type
Run Code Online (Sandbox Code Playgroud)
与...的类型相同
std::iterator_traits<T*>::value_type
Run Code Online (Sandbox Code Playgroud)
为什么它的设计是这样的?首先不应该是const T而第二个是T吗?你应该如何采用底层const正确类型的迭代器?我知道你可以编写自己的模板类和专业化并从中获取
std::iterator_traits<const T*>::pointer
Run Code Online (Sandbox Code Playgroud)
但不应该有一个成员typedef持有它吗?
我这样做:
const int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
const auto foo = cbegin(arr);
const typename iterator_traits<decltype(foo)>::value_type bar = 1;
Run Code Online (Sandbox Code Playgroud)
我本来期望bar有这种类型int.但相反,我得到一个错误:
错误C2039 ::
value_type不是.的成员std::iterator_traits<_Ty *const >
这是const我需要剥离那个什么的问题吗?
在算法中,我可以value_type通过 直接从迭代器确定iter::value_type。为什么算法会iterator_traits做同样的事情?
#include <iostream>
#include <vector>
#include <iterator>
#include <typeinfo>
using namespace std;
template<typename iter>
void for_each(iter first, iter end)
{
cout << "container value type: "
<< typeid(typename iter::value_type).name()
<< endl;
cout << "container value type: "
<< typeid(typename iterator_traits<iter>::value_type).name()
<< endl;
}
int main()
{
vector<int> v1;
for_each(begin(v1), end(v1));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
container value type: i
container value type: i
Run Code Online (Sandbox Code Playgroud) ForwardIterators是否必须是OutputIterators?我现在的STL的实现(VS2012)派生forward_iterator_tag从两个input_iterator_tag和output_iterator_tag,但我找不到标准[N3485]这个要求.
似乎迭代器适配器reverse_iterator双重定义了大多数嵌套类型.特别是,从公开继承std::iterator暴露iterator_category,value_type,difference_type,pointer和reference.除了iterator_category和之外value_type,这些都typedef在类定义中再次明确地使用.
24.5.1.1类模板reverse_iterator [reverse.iterator]
namespace std {
template <class Iterator>
class reverse_iterator : public
iterator<typename iterator_traits<Iterator>::iterator_category,
typename iterator_traits<Iterator>::value_type,
typename iterator_traits<Iterator>::difference_type,
typename iterator_traits<Iterator>::pointer,
typename iterator_traits<Iterator>::reference> {
public:
typedef Iterator iterator_type;
typedef typename iterator_traits<Iterator>::difference_type difference_type;
typedef typename iterator_traits<Iterator>::reference reference;
typedef typename iterator_traits<Iterator>::pointer pointer;
// ... rest of the class
};
Run Code Online (Sandbox Code Playgroud)
问题:为什么重复定义?这只是为了说明的目的,还是有更多的东西?为什么不重新定义iterator_category和value_type?
c++ iterator language-lawyer iterator-traits reverse-iterator
我想专门std::iterator_traits<>为一个容器类模板的迭代器,它不具有通常的嵌套类型定义(如value_type,difference_type等),其源我不应该修改.基本上我想做这样的事情:
template <typename T> struct iterator_traits<typename Container<T>::iterator>
{
typedef T value_type;
// etc.
};
Run Code Online (Sandbox Code Playgroud)
除了这不起作用,因为编译器无法推断T从Container<T>::iterator.
是否有任何工作方式来实现相同的目标?
例如:
template <typename T>
class SomeContainerFromAThirdPartyLib
{
typedef T ValueType; // not value_type!
// no difference_type
class iterator
{
typedef T ValueType; // not value_type!
// no difference_type
...
};
iterator begin() { ... }
iterator end() { ... }
...
};
Run Code Online (Sandbox Code Playgroud)
现在假设我std::count()使用此类的实例调用.据我所知,在大多数STL实现中,count()返回iterator_traits<Iterator>::difference_type.iterator_traits<I>简单的主要模板typedef …
如何以规范的方式在C++ 11中定义forward-output-iterators?
根据标准,forward_iterator只是一个input_iterator.所以相应的forward_iterator_tag只是延伸input_iterator_tag.如果我们std::iterator用来定义迭代器,我们使用什么标签作为正向输出迭代器?
定义扩展两者的私有标记是否规范forward_iterator_tag,output_iterator_tag或者是否有更好的解决方案?