2951. iterator_traits should SFINAE for void* and function pointers

Section: 27.4.1 [iterator.traits] Status: New Submitter: Billy Robert O'Neal III Opened: 2017-03-24 Last modified: 2017-07-16

Priority: 3

View all other issues in [iterator.traits].

View all issues with New status.

Discussion:

A customer recently triggered an unexpected SFINAE condition with class path. We constrain the constructor that takes const Source& by asking if iterator_traits<Source>::value_type is one that's OK. This forms iterator_traits<void*>, which is a hard error, as it tries to form void&.

Pointers-to-non-object-type can never act as iterators, as they don't support pointer arithmetic (as we recently discovered in atomic<void*> / atomic<int(*)(int)>).

[2017-07 Toronto Wed Issue Prioritization]

Priority 3; Billy to look into arrays of unknown bounds

Proposed resolution:

This wording is relative to N4659.

  1. Change 27.4.1 [iterator.traits] as indicated:

    -3- It is specialized for pointers as

    namespace std {
      template<class T> struct iterator_traits<T*> {
        using difference_type = ptrdiff_t;
        using value_type = T;
        using pointer = T*;
        using reference = T&;
        using iterator_category = random_access_iterator_tag;
      };
    }
    

    and for pointers to const as

    namespace std {
      template<class T> struct iterator_traits<const T*> {
        using difference_type = ptrdiff_t;
        using value_type = T;
        using pointer = const T*;
        using reference = const T&;
        using iterator_category = random_access_iterator_tag;
      };
    }
    

    -?- These partial specializations for pointers apply only when T is an object type.