I have a function that expects a templated iterator type.
It currently dereferences the iterator to inspect the type being iterated.
template < typename Iterator >
void func( Iterator i )
{
// Inspect the size of the objects being iterated
const size_t type_size = sizeof( *i );
...
}
I recently discovered that several of the standard iterator types, such as std::insert_iterator
define *i
as simply a reference to i
.
That is, sizeof(*i)
is the size of the iterator itself; the same as sizeof(i)
or sizeof(***i)
Is there a universal way (supporting C++ 03) to determine the size or type of objects being iterated by any standard iterator?
I'm not sure why you would want the value_type
of an OutputIterator, because there is no way to extract a value from an Output Iterator. However, the three insert iterator adaptors all define value_type
to be void
and provide a container_type
type member, so you could fall back to the value_type
of T::container_type
if the value_type
of T
turns out to be void
.
(By "value_type
of" I really mean std::iterator_traits<T::container_type>::value_type
and std::iterator_traits<T>::value_type
.)
Or you could just not try to use Output Iterators as though they had values :)
Edit: SFINAE isn't necessary: (even without C++11 niceness)
template<typename U, typename T> struct helper {typedef U type;};
// ostream*_iterator handling courtesy Drew Dormann
template <typename T, typename charT, typename traits>
struct helper<void, std::ostream_iterator<T, charT, traits> > {typedef T type;};
template <typename charT, typename traits>
struct helper<void, std::ostreambuf_iterator<charT, traits> > {typedef charT type;};
// std::raw_storage_iterator still needs an override
// as well as any non-standard output iterators which don't define a container_type.
template<typename T> struct helper<void, T>
{typedef typename std::iterator_traits<typename T::container_type>::value_type type;};
typedef<typename It> struct my_value_type
: public helper<typename std::iterator_traits<It>::value_type, It> {};