Opened 4 years ago

#13644 new Bugs

std::iterator_traits<>::value_type is always non-const for any kind of boost::iterator_facade Iterator

Reported by: Florian Reiser <florian.reiser@…> Owned by: jeffrey.hellrung
Milestone: To Be Determined Component: iterator
Version: Boost 1.67.0 Severity: Problem
Keywords: iterator_facade Cc:

Description

I've found a bug in boost::iterator_facade. If you define your own iterator by using the facade and you try to deduce the value_type of the iterator by using std::iterator_traits, the type is always non-const independently of the iterator value type declaration.

You can reproduce this with the following test program:

#include <iterator>
#include <boost/iterator/iterator_facade.hpp>


template <typename Value>
class IteratorTest
        : public boost::iterator_facade<
        IteratorTest<Value>
        , Value
        , boost::forward_traversal_tag
        >
{
public:
        IteratorTest() {};

private:
        Value m_value{};
        friend class boost::iterator_core_access;
        template <class> friend class IteratorTest;

        template <typename OtherIteratorType>
        inline bool equal(const IteratorTest<OtherIteratorType>& other) const {
                return true;
        }

        void increment() {
        }

        inline Value& dereference() const noexcept {
                return m_value;
        }
};

template <typename T>
class DeduceType;

int main()
{
        using iterator = IteratorTest<int>;
        using const_iterator = IteratorTest<const int>;

        auto it = iterator();
        auto cit = const_iterator();

        DeduceType<decltype(it)> debug1;
        DeduceType<decltype(cit)> debug2;
        DeduceType<std::iterator_traits<decltype(it)::value_type>> debug3;
        DeduceType<std::iterator_traits<decltype(cit)::value_type>> debug4;
}

With my VS2017 compiler, I receive the following compiler output (I've omitted the implementation of DeduceType to force the compiler to tell me the type; so the compiler error here is not an Error)

1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(46): error C2079: 'debug1' uses undefined class 'DeduceType<iterator>'
1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(47): error C2079: 'debug2' uses undefined class 'DeduceType<const_iterator>'
1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(48): error C2079: 'debug3' uses undefined class 'DeduceType<std::iterator_traits<int>>'
1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(49): error C2079: 'debug4' uses undefined class 'DeduceType<std::iterator_traits<int>>'

I've found the reason for this bug in boost/iterator/iterator_facade.hpp:120

    template <
        class ValueParam
      , class CategoryOrTraversal
      , class Reference
      , class Difference
    >
    struct iterator_facade_types
    {
        typedef typename facade_iterator_category<
            CategoryOrTraversal, ValueParam, Reference
        >::type iterator_category;

        typedef typename remove_const<ValueParam>::type value_type;

If you change the line

typedef typename remove_const<ValueParam>::type value_type;

to

typedef ValueParam value_type;

the output of my test program is as expected:

1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(46): error C2079: 'debug1' uses undefined class 'DeduceType<iterator>'
1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(47): error C2079: 'debug2' uses undefined class 'DeduceType<const_iterator>'
1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(48): error C2079: 'debug3' uses undefined class 'DeduceType<std::iterator_traits<int>>'
1>c:\users\florian\source\repos\iterator_facade_const_bug\iterator_facade_const_bug\reproducebug.cpp(49): error C2079: 'debug4' uses undefined class 'DeduceType<std::iterator_traits<const int>>'

Change History (0)

Note: See TracTickets for help on using tickets.