v3 требования к make_iterator_range

Я пытаюсь преобразовать свой диапазон (пара итераторов) в iterator_range, чтобы я мог использовать все представления и действия. Я могу преобразовать свой диапазон в boost::iterator_range, но получаю ошибку компиляции при преобразовании в range::v3. Вот минимальный пример:

struct MyRange
{
    struct iterator_t : std::iterator<std::input_iterator_tag, int>
    {
        friend bool operator==(const iterator_t& lhs, const iterator_t& rhs);
        friend bool operator!=(const iterator_t& lhs, const iterator_t& rhs);
    };
    iterator_t begin() { return iterator_t{}; };
    iterator_t end() { return iterator_t{}; };
};

int main(int argc, char *argv[])
{
    auto my_range    = MyRange{};
    auto boost_range = boost::make_iterator_range(my_range.begin(), my_range.end()); // works
    auto v3_range    = ranges::v3::make_iterator_range(my_range.begin(), my_range.end()); // doesn't compile
}

Похоже, мне нужно что-то сделать, чтобы удовлетворить концепцию Sentinel iterator_range, но я не смог понять, что именно. Любая помощь приветствуется!

Изменить: я компилирую с помощью gcc54 -std=c++14. Ошибки компиляции range v3/c++ довольно длинные, но вот фрагмент:

range-v3/include/range/v3/iterator_range.hpp:171:17: note: in expansion of macro 'CONCEPT_REQUIRES_'
             CONCEPT_REQUIRES_(Sentinel<S, I>())>
             ^
range-v3/include/range/v3/utility/concepts.hpp:669:15: note: invalid template non-type parameter
 >::type = 0                                                                     \
           ^
range-v3/include/range/v3/iterator_range.hpp:171:17: note: in expansion of macro 'CONCEPT_REQUIRES_'
             CONCEPT_REQUIRES_(Sentinel<S, I>())>

person skgbanga    schedule 28.03.2017    source источник
comment
Какой сбой компиляции вы получаете?   -  person cdhowie    schedule 28.03.2017
comment
@cdhowie Отредактировано с фрагментом ошибки компиляции.   -  person skgbanga    schedule 28.03.2017
comment
Для значения итератора i выражения *i и ++i должны быть правильно сформированы (хотя фактическое вычисление этих выражений может быть неправильным, например, для значений итератора, находящихся за концом). Добавление этих операторов к вашему типу iterator_t может разрешить компиляцию. Вам также может понадобиться специализация std::iterator_traits для вашего типа MyRange::iterator_t.   -  person cdhowie    schedule 28.03.2017
comment
Я думаю причина не в этом. например coliru.stacked-crooked.com/a/f3f761128e23bc1b в этом я добавил *i и ++i, но все равно не компилируется. Также версия boost отлично компилируется (даже без них). Я думаю, что мы что-то упускаем здесь.   -  person skgbanga    schedule 28.03.2017
comment
В этом примере он не компилируется из-за error: no member named 'make_iterator_range' in namespace 'ranges::v3'; did you mean 'boost::make_iterator_range'?, а не из-за того, что что-то связано с MyRange::iterator_t.   -  person cdhowie    schedule 28.03.2017
comment
@cdhowie это потому, что я не смог найти онлайн-компилятор, у которого в пути включения есть заголовки диапазона v3. :)   -  person skgbanga    schedule 28.03.2017
comment
В частности, WeaklyIncrementable требует, чтобы тип различия вашего итератора проходил std::is_integral. Я не уверен на 100%, где он пытается получить этот тип, но я предполагаю, что std::iterator_traits<MyRange::iterator_t>::difference_type.   -  person cdhowie    schedule 28.03.2017
comment
Похоже, он ищет MyRange::iterator_t::difference_type необходимо определить. Я предполагаю, что он также потребует, чтобы operator- возвращал difference_type для получения разницы между итераторами.   -  person cdhowie    schedule 28.03.2017
comment
Если вы сделаете свой iterator фактически удовлетворяющим требованиям итератора, тогда ваш диапазон будет удовлетворять требованиям диапазона, и вам не нужно make_iterator_range.   -  person Casey    schedule 28.03.2017
comment
@Casey Требования iterator, упомянутые здесь: en.cppreference.com/w/cpp/concept /Iterator не требует многого. И ссылка на coliru: coliru.stacked-crooked.com/a/090f4b56b47b88ef (показано только для кода, а не для компиляции!) удовлетворяют всем требованиям. (по крайней мере я так думаю). И я думаю, что iterator_range предоставляет хорошие псевдонимы/типы, которые требуются для определенных алгоритмов.   -  person skgbanga    schedule 28.03.2017
comment
Ваш итератор (а) не имеет оператора постинкремента (operator++(int)) и (б) имеет не-const operator*. И нет, уверяю вас, что iterator_range — это просто диапазон, как и любой другой, без особых качеств. Его цель — предоставить механизм формирования диапазона, когда у вас есть итератор и часовой.   -  person Casey    schedule 29.03.2017
comment
См. coliru.stacked-crooked.com/a/71eca3161805edfb. (У Колиру есть древний диапазон v3, из темных веков, когда iterator_range и make_iterator_range назывались range и make_range.)   -  person Casey    schedule 29.03.2017
comment
Вот Это Да! Спасибо! Я думаю, что нам определенно нужны лучшие сообщения об ошибках для них. Вы хотите официально ответить на этот вопрос, и я могу отметить его как правильный ответ.   -  person skgbanga    schedule 29.03.2017


Ответы (1)


Ваш итератор не является итератором. У него нет разыменования, пре- или постинкремента.

auto my_range    = MyRange{};
auto i           = my_range.begin();
*i;
++i;
i++;

причины:

prog.cc: In function 'int main()':
prog.cc:20:5: error: no match for 'operator*' (operand type is 'MyRange::iterator_t')
     *i;
     ^~
prog.cc:21:5: error: no match for 'operator++' (operand type is 'MyRange::iterator_t')
     ++i;
     ^~~
prog.cc:22:6: error: no 'operator++(int)' declared for postfix '++' [-fpermissive]
     i++;
     ~^~
person Eric Niebler    schedule 11.06.2017