Skip to content

Weird SizedRange compilation problem #237

@adah1972

Description

@adah1972

The following code shows a compilation problem:

#include <experimental/ranges/concepts>
#include <experimental/ranges/ranges>
#include <iostream>
#include <iterator>
#include <string>

/** Class to allow iteration over all lines from an input stream. */
class istream_line_reader {
public:
    /**
     * Iterator that contains the line content.
     *
     * The iterator \e owns the content.
     */
    class iterator  // implements InputIterator
    {
    public:
        typedef int                     difference_type;
        typedef std::string             value_type;
        typedef value_type*             pointer_type;
        typedef value_type&             reference;
        typedef std::input_iterator_tag iterator_category;

        iterator() : _M_stream(nullptr) {}
        explicit iterator(std::istream& is) : _M_stream(&is)
        {
            ++*this;
        }

        reference operator*()
        {
            assert(_M_stream != nullptr);
            return _M_line;
        }
        pointer_type operator->()
        {
            assert(_M_stream != nullptr);
            return &_M_line;
        }
        iterator& operator++()
        {
            assert(_M_stream != nullptr);
            getline(*_M_stream, _M_line);
            if (!*_M_stream)
                _M_stream = nullptr;
            return *this;
        }
        iterator operator++(int)
        {
            iterator temp(*this);
            ++*this;
            return temp;
        }

        bool operator==(const iterator& rhs) const
        {
            return _M_stream == rhs._M_stream;
        }
        bool operator!=(const iterator& rhs) const
        {
            return !operator==(rhs);
        }

    private:
        std::istream* _M_stream;
        std::string   _M_line;
    };

    istream_line_reader() noexcept
        : _M_stream(nullptr)
    {
    }
    explicit istream_line_reader(std::istream& is) noexcept
        : _M_stream(&is)
    {
    }
    iterator begin()
    {
        return iterator(*_M_stream);
    }
    iterator end() const
    {
        return iterator();
    }

private:
    std::istream* _M_stream;
};

#define TEST_CONCEPT(Concept, Type...) \
    cout << #Concept << '<' << #Type << ">: " << Concept<Type> << endl

int main()
{
    namespace ranges = std::experimental::ranges;
    using ranges::Range;
    using ranges::View;
    using ranges::SizedRange;
    using std::cout;
    using std::endl;
    cout << std::boolalpha;
    auto line_reader = istream_line_reader(std::cin);
    auto rng = line_reader | ranges::view::take(5);
    TEST_CONCEPT(Range, decltype(line_reader));
    TEST_CONCEPT(View, decltype(line_reader));
    TEST_CONCEPT(SizedRange, decltype(line_reader));
    TEST_CONCEPT(Range, decltype(rng));
    TEST_CONCEPT(View, decltype(rng));
    TEST_CONCEPT(SizedRange, decltype(rng));  // DOESN'T COMPILE
    for (auto& line : rng) {
        cout << line << endl;
    }
}

I intend to check which concepts are satisfied. However, the line TEST_CONCEPT(SizedRange, decltype(rng)); (marked above) does not compile. I expect to see it compile and output false at run time.

Which one is at fault, my code, CMCSTL2, or GCC? I doubt it is GCC this time, but I would like to hear experts’ opinions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions