c++decltypeiterator-traits

Why decltype() yelds a pointer to reference?


I'm trying to get a better knowledge about iterator_traits and found a snippet of code on a C++ textbook. So I've added some code to make it executable with the aim to understand the behaviour of that said compile-time mechanism. The complete program looks like so:

template<typename C>
    using Iterator_type = typename C::iterator;  

template<typename Iter>
    using Iterator_category = typename std::iterator_traits<Iter>::iterator_category;   

template<typename Ran>                                          
void sort_helper(Ran beg, Ran end, std::random_access_iterator_tag)   
{
    sort(beg, end);   
}

template<typename For>                                     
void sort_helper(For beg, For end, std::forward_iterator_tag)   
{
    std::vector<decltype(*beg)> v {beg, end};   
    sort(v.begin(), v.end());
    copy(v.begin(), v.end(), beg);              
}

template<typename C>
void sort(C& c)
{
    using Iter = Iterator_type<C>;
    sort_helper(c.begin(), c.end(), Iterator_category<Iter>{});
}

void test(std::vector<std::string>& v, std::forward_list<int>& lst)
{
    sort(v);     
    sort(lst);   
}

template<typename C>
void print(C& c)
{
    for(auto it = c.begin(); it != c.end(); ++it) {
        std::cout << *it << '\n';
    }
    std::cout << '\n';
}

int main()
{
    std::vector<std::string> v { "Bicycle", "Hoovercraft", "Rocket", "Airplaine", "Bus", "Submarine" };
    print(v);

    sort(v);
    print(v);

    std::forward_list<int> lst { 2, 81, 3, 0, 4, 34, 23, 11 };
    print(lst);

    sort(lst);
    print(lst);

    return 0;
} 

The compilation fails telling that a pointer to reference is given:

memory:1723:16: error: 
  'pointer' declared as a pointer to a reference of type 'int &'
typedef _Tp*              pointer;

and the error stack brings to the following line:

in instantiation of template class 'std::__1::vector<int &,     std::__1::allocator<int &> >'
  requested here
std::vector<decltype(*beg)> v {beg, end};

this compiling either on Mac OS and on a Linux machine with g++.

I managed it to work modifying the involved part like so:

auto i = *beg;
std::vector<decltype(i)> v {beg, end};

Can you please give me a clearer explanation on why the decltype() function is returning a pointer to a reference? I've read some other questions regarding the decltype type function on SO and also have read the specifications but neither brought me on the right path, nor examining the full compiler stack of output messages was of any help.

Thank you in advance for any consideration.


Solution

  • The problem is that the decltype yields a reference type (you cannot make std::vector of).
    Why is that so is answered here in-depth.

    You can fix it by either of the two ways: