Compile error with decltype of iterator de-reference

What am I missing here? Why can't I use decltype to define the value_type of an iterator? The code below gets inscrutable compile-time errors when I use decltype rather than iterator_traits, but only if I also use value_type to declare a vector.

Visual Studio 2017, C++17 rev. 15.6 Preview

#include <vector>
template<class Ptr >
void foo(Ptr beg) {
    *beg = 1;  // Cool, babies.
//  using value_type = decltype(*beg); // COMPILER ERROR when buf declared below
    using value_type = typename std::iterator_traits<Ptr>::value_type;
    std::vector<value_type> buf(1); // Remove this and decltype compiles.
}

int main() {
    std::vector<int> bar(1);
    foo(std::begin(bar));
    *(std::begin(bar)) = 1;
    return 0;
}

By request...

error C2528: 'const_pointer': pointer to reference is illegal

1 answer

  • answered 2018-01-17 04:10 Sam Varshavchik

    It's for the same reason when you have:

    void foo(int *beg)
    

    then

    decltype(*beg)
    

    Does not give you an int. You get an int & here. That's what, essentially, your using declaration ends up getting: a reference, an uninvited hitch-hiker.

    If you insist on using decltype, you can do:

    using value_type = typename std::remove_reference<decltype(*beg)>::type;
    

    In order to ditch the unwelcome hitch-hiker.