In my project, I want to split stream into some given type of values, so I implement a template function as
template <typename TElem, typename TOutputIter>
TOutputIter SplitSpace(std::istream& IS, TOutputIter result)
{
TElem elem;
while (IS >> elem)
{
*result = elem;
++result;
}
return result;
}
I think this is awkward since I have to explicitly given the type of TElem
when calling it. For example, I have to write:
std::vector<int> v;
SplitSpace<int>(std::cin, back_inserter(v));
// I want to it to be SplitSpace(std::cin, back_inserter(v));
I tried to obtain the value type from an (template) iterator and used std::iterator_traits
as follows:
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;
}
However, the above codes do not work for back_insert_iterator
. I checked the source codes of back_insert_iterator/front_insert_iterator/insert_iterator
in std
namespace and found the value_type/difference_type/pointer/reference
are all void
.
I would like to know why these types are all void
, is there any consideration for this? Another question is that is it possible to implement the SplitSpace
function without explicitly giving the element type when call it? Thanks.
value_type
does not make much sense in the case of OutputIterators, because an output iterator does not give access to any values, and more importantly it can accepts a wide range of value types.
The only requirement for an OutputIterator it
is that it must supports the expression *it = o
where o
is a value of some type that is in the set of types that are writable to the particular iterator type of i (§24.2.1). This means that an output iterator can potentially accepts a wide range of types: for instance, its operator*
can return a proxy object that overloads operator=
for a variety of types ; what should be value_type
in this case?
For instance, consider the following output iterator:
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
};
There is no sensible choice for value_type
here.
The same reasoning applies to pointer
and reference_type
. difference_type
is not defined because you cannot calculate the distance between two output iterators, as they are single-pass.
N.B.: the standard explicitely states that insert_iterator
and its siblings must inherits from iterator<output_iterator_tag, void, void, void, void>
, so this is not a peculiarity of your implementation.
As mentioned by Luc in the comments what you want to do can be easily done with the standard library:
std::vector<int> v;
std::copy( std::istream_iterator( std::cin )
, std::istream_iterator()
, std::back_inserter( v ) );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With