Index: llvm/include/llvm/ADT/STLExtras.h =================================================================== --- llvm/include/llvm/ADT/STLExtras.h +++ llvm/include/llvm/ADT/STLExtras.h @@ -645,9 +645,7 @@ public: zip_common(Iters &&... ts) : iterators(std::forward(ts)...) {} - value_type operator*() { return deref(std::index_sequence_for{}); } - - const value_type operator*() const { + value_type operator*() const { return deref(std::index_sequence_for{}); } @@ -818,8 +816,6 @@ : iterators(std::forward(ts.first)...), end_iterators(std::forward(ts.second)...) {} - value_type operator*() { return deref(std::index_sequence_for{}); } - value_type operator*() const { return deref(std::index_sequence_for{}); } @@ -1894,8 +1890,7 @@ } std::size_t index() const { return Index; } - const value_reference value() const { return *Iter; } - value_reference value() { return *Iter; } + value_reference value() const { return *Iter; } private: std::size_t Index = std::numeric_limits::max(); @@ -1904,10 +1899,8 @@ template class enumerator_iter - : public iterator_facade_base< - enumerator_iter, std::forward_iterator_tag, result_pair, - typename std::iterator_traits>::difference_type, - typename std::iterator_traits>::pointer> { + : public iterator_facade_base, std::forward_iterator_tag, + const result_pair> { using result_type = result_pair; public: @@ -1917,7 +1910,6 @@ enumerator_iter(std::size_t Index, IterOfRange Iter) : Result(Index, Iter) {} - result_type &operator*() { return Result; } const result_type &operator*() const { return Result; } enumerator_iter &operator++() { Index: llvm/include/llvm/ADT/iterator.h =================================================================== --- llvm/include/llvm/ADT/iterator.h +++ llvm/include/llvm/ADT/iterator.h @@ -42,8 +42,7 @@ /// (All of the following methods) /// - DerivedT &operator=(const DerivedT &R); /// - bool operator==(const DerivedT &R) const; -/// - const T &operator*() const; -/// - T &operator*(); +/// - T &operator*() const; /// - DerivedT &operator++(); /// /// Bidirectional Iterators: @@ -296,8 +295,7 @@ return LHS.I < RHS.I; } - const ReferenceT operator*() const { return *I; } - ReferenceT operator*() { return *I; } + ReferenceT operator*() const { return *I; } }; /// An iterator type that allows iterating over the pointees via some @@ -349,8 +347,7 @@ explicit pointer_iterator(WrappedIteratorT u) : pointer_iterator::iterator_adaptor_base(std::move(u)) {} - T &operator*() { return Ptr = &*this->I; } - const T &operator*() const { return Ptr = &*this->I; } + T &operator*() const { return Ptr = &*this->I; } }; template ::iterator_category, typename std::iterator_traits>::iterator_category>; +// Check that dereferencing works correctly adapting pointers and proxies. +template +struct PointerWrapper : public iterator_adaptor_base, T *> { + PointerWrapper(T *I) : iterator_adaptor_base(I) {} +}; +struct IntProxy { + int &I; + IntProxy(int &I) : I(I) {} + void operator=(int NewValue) { I = NewValue; } +}; +struct ConstIntProxy { + const int &I; + ConstIntProxy(const int &I) : I(I) {} +}; +template +struct PointerProxyWrapper + : public iterator_adaptor_base, T *, + std::random_access_iterator_tag, T, + ptrdiff_t, T *, ProxyT> { + PointerProxyWrapper(T *I) + : iterator_adaptor_base(I) {} +}; +using IntIterator = PointerWrapper; +using ConstIntIterator = PointerWrapper; +using IntProxyIterator = PointerProxyWrapper; +using ConstIntProxyIterator = PointerProxyWrapper; + +template ::value, bool> = false> +constexpr bool canAssignFromInt(T &&) { + return true; +} +template ::value, bool> = false> +constexpr bool canAssignFromInt(T &&) { + return false; +} + +TEST(IteratorAdaptorTest, Dereference) { + int Number = 1; + + // Construct some iterators and check whether they can be assigned to. + IntIterator I(&Number); + const IntIterator IC(&Number); + ConstIntIterator CI(&Number); + const ConstIntIterator CIC(&Number); + EXPECT_EQ(true, canAssignFromInt(*I)); // int * + EXPECT_EQ(true, canAssignFromInt(*IC)); // int *const + EXPECT_EQ(false, canAssignFromInt(*CI)); // const int * + EXPECT_EQ(false, canAssignFromInt(*CIC)); // const int *const + + // Prove that dereference and assignment work. + EXPECT_EQ(1, *I); + EXPECT_EQ(1, *IC); + EXPECT_EQ(1, *CI); + EXPECT_EQ(1, *CIC); + *I = 2; + EXPECT_EQ(2, Number); + *IC = 3; + EXPECT_EQ(3, Number); + + // Construct some proxy iterators and check whether they can be assigned to. + IntProxyIterator P(&Number); + const IntProxyIterator PC(&Number); + ConstIntProxyIterator CP(&Number); + const ConstIntProxyIterator CPC(&Number); + EXPECT_EQ(true, canAssignFromInt(*P)); // int * + EXPECT_EQ(true, canAssignFromInt(*PC)); // int *const + EXPECT_EQ(false, canAssignFromInt(*CP)); // const int * + EXPECT_EQ(false, canAssignFromInt(*CPC)); // const int *const + + // Prove that dereference and assignment work. + EXPECT_EQ(3, (*P).I); + EXPECT_EQ(3, (*PC).I); + EXPECT_EQ(3, (*CP).I); + EXPECT_EQ(3, (*CPC).I); + *P = 4; + EXPECT_EQ(4, Number); + *PC = 5; + EXPECT_EQ(5, Number); +} + // pointeE_iterator static_assert(IsAdaptedIterCategorySame::value, "");