在我的项目中,我想将流分割为某些给定类型的值,因此我将模板函数实现为
template <typename TElem, typename TOutputIter>
TOutputIter SplitSpace(std::istream& IS, TOutputIter result)
{
TElem elem;
while (IS >> elem)
{
*result = elem;
++result;
}
return result;
}
我认为这很尴尬因为我必须在调用它时明确给出TElem
的类型。例如,我必须写:
std::vector<int> v;
SplitSpace<int>(std::cin, back_inserter(v));
// I want to it to be SplitSpace(std::cin, back_inserter(v));
我试图从(模板)迭代器中获取值类型,并使用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;
}
但是,上述代码不适用于back_insert_iterator
。我检查了back_insert_iterator/front_insert_iterator/insert_iterator
命名空间中std
的源代码,发现value_type/difference_type/pointer/reference
都是void
。
我想知道为什么这些类型都是void
,对此有何考虑?另一个问题是,在调用它时,是否可以实现SplitSpace
函数而不显式给出元素类型?感谢。
答案 0 :(得分:6)
value_type
没有多大意义,因为输出迭代器不允许访问任何值,更重要的是它可以接受多种值类型。
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
};
这里value_type
没有明智的选择。
同样的推理适用于pointer
和reference_type
。 difference_type
未定义,因为您无法计算两个输出迭代器之间的距离,因为它们是单遍的。
N.B。:该标准明确规定insert_iterator
及其兄弟姐妹必须继承自iterator<output_iterator_tag, void, void, void, void>
,因此这不是您实施的特点。
答案 1 :(得分:4)
如果您只想找到避免指定TElem
模板参数的方法,可以使用以下方法:
template <typename TOutputIter>
TOutputIter SplitSpace(std::istream& IS, TOutputIter result)
{
typedef typename TOutputIter::container_type::value_type TElem;
TElem elem;
while (IS >> elem)
{
*result = elem;
++result;
}
return result;
}
...当然,根据你假装使用的TOutputIter类型,你不应该使用这种方法。
答案 2 :(得分:3)
正如Luc在评论中所提到的,您可以使用标准库轻松完成您想要做的事情:
std::vector<int> v;
std::copy( std::istream_iterator( std::cin )
, std::istream_iterator()
, std::back_inserter( v ) );
答案 3 :(得分:2)
AFAIK,您应该能够从迭代器中获取container_type
,从中您应该能够获得value_type
。您可能希望在某个时候专注于pair
。这应该回答第二部分,第一部分;不确定......