Search code examples
c++iteratorsfinae

Is it possible to deduce the contained type for std::insert_iterator?


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?


Solution

  • 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> {};