ошибка: выведенный тип класса "кортеж" в типе возвращаемого значения функции

Чем я занимаюсь

Я практикую C ++ через 3 года. Мне нужно было учиться быстро и широко, поэтому этот пример, который я пытаюсь решить, может показаться вам странным.

Я использую c++20, gcc 10.2.

Я хотел сделать функцию перечисления Python, которая

  • Принимает любые container<T>
  • Урожайность std::tuple<int, T>
  • Где T - это тип элементов в контейнере

Я хотел попробовать применить питонический диапазон в качестве аргумента enumerate, который

  • Принимает (int start, int end, int step)
  • Урожайность int i с start до end каждые step

диапазон (это не мой код, я только добавил step функции)

template <typename T>
class range_iterator;

template <typename T>
class range_impl
{
    const T start_;
    const T stop_;
    const T step_;

public:
    range_impl(T start, T stop, T step) : start_{start}, stop_{stop}, step_{step} {};
    range_impl(T start, T stop) : start_{start}, stop_{stop}, step_{1} {};
    range_impl(T stop) : start_{0}, stop_{stop}, step_{1} {};

    range_iterator<T> begin() const
    {
        return range_iterator<T>{start_, step_};
    }

    range_iterator<T> end() const
    {
        return range_iterator<T>{stop_, step_};
    }
};

template <typename T>
class range_iterator
{
    T current_;
    const T step_;

public:
    range_iterator(T init, T step) : current_{init}, step_{step} {};

    range_iterator<T> &operator++()
    {
        current_ += step_;
        return *this;
    }

    bool operator!=(const range_iterator<T> &rhs) const
    {
        return current_ != rhs.current_;
    }

    T operator*() const
    {
        return current_;
    }
};

template <typename T>
range_impl<T> range(const T start, const T stop, const T step)
{
    return range_impl<T>(start, stop, step);
}

template <typename T>
range_impl<T> range(const T start, const T stop)
{
    return range_impl<T>(start, stop);
}

template <typename T>
range_impl<T> range(const T stop)
{
    return range_impl<T>(stop);
}

Может использоваться следующим образом

#include <iostream>
int main()
{
    for(auto i: range(0, 100 2)
    {
        std::cout << i << std::endl;
    }
}

Код проблемы: перечислить

template <typename T>
class enumerate_iterator;

// Here, T should be a type of a container that contains type X 
template <typename T>
class enumerate_impl
{
    T impl;

public:
    enumerate_impl<T>(T impl) : impl{impl} {/* empty */};

    enumerate_iterator begin() const
    {
        return enumerate_iterator{impl.begin()};
    }

    enumerate_iterator end() const
    {
        return enumerate_iterator{impl.end()};
    }
};


// Here, T should be a type of a iterator, I think. Confused myself.
template <typename T>
class enumerate_iterator
{

    T iterator;
    int i;

public:
    enumerate_iterator(T iterator) : iterator{iterator}, i{0} {/* empty body */};

    enumerate_iterator<T> &operator++()
    {
        i++;
        iterator++;
        return *this;
    }

    bool operator!=(const enumerate_iterator<T> &rhs) const
    {
        return iterator != rhs.iterator;
    }

    std::tuple operator*() const
    {
        return {i, *iterator};
    }
};

template <typename T>
enumerate_impl<T> enumerate(T impl)
{
    return enumerate_impl<T>{impl};
}

Ожидаемое использование

#include <iostream>
int main()
{
    for (auto &[i, j] : enumerate(range(0, 100, 2)))
    {
        std::cout << i << " " << j << std::endl;
    }
}

Полученная ошибка (на самом деле ошибок компиляции очень много, но я хочу попробовать больше с другими).

utility.cpp:186:20: error: deduced class type 'tuple' in function return type
  186 |         std::tuple operator*() const

Я догадался, что это жалуется you didn't tell me what type the tuple contains. Но дело в том, что я не знаю, какой тип T iterator содержит. Как я могу сказать return type is std::tuple<int, type T contains>?

Спасибо, что прочитали этот длинный длинный вопрос.


person Inyoung Kim 김인영    schedule 07.03.2021    source источник
comment
Не мой код Ужасный код. Это даже не допустимый диапазон C ++. Нет смысла иметь итераторы, если вы не можете их ни с чем использовать.   -  person Nicol Bolas    schedule 08.03.2021


Ответы (1)


Я думаю, что, возможно, для enumerate_iterator вы можете захотеть, чтобы его тип шаблона T был типом базового элемента, а не каким-то составным типом итерации.

Например, если вы решили реализовать свою итерацию с использованием указателей необработанной памяти, то член данных enumerate_iterator с именем iterator будет иметь тип T* (вместо текущего типа T).

И тогда, в этом случае, определение operator*() будет запрограммировано как имеющее тип возврата std::tuple<int,T>

person Cow Corporation    schedule 08.03.2021