1051. Specify subscript operation return types of reverse_iterator and move_iterator

Section: 27.5.1.3.12 [reverse.iter.opindex], 27.5.3.3.12 [move.iter.op.index] Status: NAD Submitter: Alisdair Meredith Opened: 2009-03-12 Last modified: 2017-03-22

Priority: Not Prioritized

View all other issues in [reverse.iter.opindex].

View all issues with NAD status.

Discussion:

Addresses UK 279 [CD1]

The reason the return type became unspecified is LWG issue 386. This reasoning no longer applies as there are at least two ways to get the right return type with the new language facilities added since the previous standard.

Proposal: Specify the return type using either decltype or the Iter concept_map.

[ Summit: ]

Under discussion. This is a general question about all iterator adapters.

[ Howard adds post Summit: ]

I am requesting test cases to demonstrate a position.

[ 2009-07-24 Daniel adds: ]

I recommend NAD. Without concepts we can no longer restrict this member in a trivial way. Using decltype the declaration would be along the lines of

static const Iter& __base(); // not defined
auto operator[](difference_type n) const -> decltype(__base()[-n-1]);

but once reverse_iterator is instantiated for some given type Iter which cannot form a well-formed expression __base()[-n-1] this would cause an ill-formed function declaration, diagnostic required, and no silent SFINAE elimination.

[ 2009-10 Santa Cruz: ]

Moved to NAD.

[ 2009-10-22 Daniel adds: ]

IMO, my original comment regarding ill-formedness of the described construction is still correct, but I must add that I should weaken my assertion "Without concepts we can no longer restrict this member in a trivial way".

In fact with the existence of default template arguments for function templates it is not too hard to implement this like as follows, which shows that we can indeed simulate to some sense constrained member functions in C++0x.

My example does not really proof that the specification is easy, but it should be possible. I assume that the implementation would not be ABI compatible, though.

It is now your own decision how to proceed ;-)

#include <type_traits>
#include <cstddef>

template<class T>
typename std::add_rvalue_reference<T>::type declval();

template<class It>
struct reverse_iterator {
    It base;
    
    typedef std::ptrdiff_t difference_type;
    
    template<class U = It, class Res =
     decltype(declval<const U&>()[declval<difference_type>()])
    >
    Res operator[](difference_type n) const  {
        return base[-n-1];
    }    
};

struct MyIter {
};

int main() {
    reverse_iterator<int*> ri;
    ri[0] = 2;
    reverse_iterator<MyIter> ri2;
}

The above declaration could be simplified, but the ideal solution

template<class U = It>
  decltype(declval<const U&>()[declval<difference_type>()])
     operator[](difference_type n) const;

does not work yet on gcc 4.4.1.

Proposed resolution: