为什么back_insert_iterator/front_insert_iterator/insert_iterator的value_type/difference_type/pointer/reference都是无效的?

Yun*_*ang 19 c++ types iterator 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_iteratorstd的命名空间,发现value_type/difference_type/pointer/reference都是void.

我想知道为什么这些类型都是void,有什么考虑吗?另一个问题是,SplitSpace在调用它时,是否可以实现该函数而不显式给出元素类型?谢谢.

Luc*_*lle 6

value_type 在OutputIterators的情况下没有多大意义,因为输出迭代器不允许访问任何值,更重要的是它可以接受各种值类型.

对OutputIterator的唯一要求it是它必须支持表达式*it = o ,其中o是某些类型的值,该类型在可写入特定迭代器类型i(第24.2.1节)的类型集中.这意味着输出迭代器可以接受多种类型:例如,它operator*可以返回operator=为各种类型重载的代理对象; value_type这种情况应该是什么?

例如,考虑以下输出迭代器:

struct SwallowOutputIterator : 
    public std::iterator<output_iterator_tag, void, void, void, void>
{
    struct proxy // swallows anything
    {
        template <typename T>
        void operator=(const T &) {}
    };

    proxy operator*() 
    {
        return proxy();
    }

    // increment operators
};
Run Code Online (Sandbox Code Playgroud)

这里没有明智的选择value_type.

同样的推理适用于pointerreference_type.difference_type未定义,因为您无法计算两个输出迭代器之间的距离,因为它们是单通道.

注意:标准明确指出它insert_iterator和兄弟姐妹必须继承iterator<output_iterator_tag, void, void, void, void>,因此这不是你的实现的特殊性.


Nim*_*Nim 2

AFAIK,您应该能够container_type从迭代器获取 ,从中您应该能够获取value_type. pair您可能想在某个时候专门从事某项工作。这应该回答第二部分,就像第一部分一样;没有把握...