Я создаю функцию, которая принимает итеративный (контейнер), а его методы начала и конца возвращают итератор, разыменование которого можно изменить с помощью переданной лямбды. Звучит сложно, но я пытаюсь сделать что-то вроде супер аккуратного Python
modified_iterator = (fn(x) for x in my_iterator)
код:
template<typename Container, typename Fn>
class IterableWrapper {
public:
template<typename Iterator>
class IteratorWrapper : public Iterator {
public:
template<typename ...Args>
explicit IteratorWrapper(Fn fn, Args ... args) : Iterator(args ...), fn(fn) {}
//typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> not working
typename std::invoke_result_t<Fn,uint64_t> operator* () const {
return fn(Iterator::operator*());
}
private:
Fn fn;
};
IterableWrapper(const Container&& c, Fn&& fn) : c(std::move(c)), fn(std::forward<Fn>(fn)) {}
auto begin() const {
return IteratorWrapper<decltype(c.begin())>(fn, c.begin());
};
auto end() const {
return IteratorWrapper<decltype(c.end())>(fn, c.end());
};
private:
Container c;
Fn fn;
};
template<typename C, typename Fn>
auto wrap_iterable(C& c, Fn&& fn) = delete;
template<typename C, typename Fn>
auto wrap_iterable(C&& c, Fn&& fn) {
return IterableWrapper<C, Fn>(std::move(c), std::forward<Fn>(fn));
}
желаемое использование:
auto new_iterable = wrap_iterable(std::vector<uint64_t>{1,2,3,4}, [](auto&& item) { return std::pow(item, 2); });
Я не хочу жестко кодировать uint64_t
в invoke_result в IteratorWrapper::operator*
. Это должен быть тип возврата operator*
в базовом классе (это шаблонный тип Iterator
).
Но замена жестко закодированного заголовка закомментированным типом возврата приводит к ошибке компиляции. Новый заголовок:
typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> operator* () const
ошибка:
In file included from /Users/adam/school/cpp/invertedindex/main.cpp:203:0:
/Users/adam/school/cpp/invertedindex/inverted_index.hpp:61:105: error: template argument 1 is invalid
typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> operator* () const { // typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> not compiling??
^~
/Users/adam/school/cpp/invertedindex/inverted_index.hpp:61:121: error: template argument 2 is invalid
typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> operator* () const { // typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> not compiling??
^~~~~
/Users/adam/school/cpp/invertedindex/inverted_index.hpp:61:127: error: expected identifier before '{' token
typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> operator* () const { // typename std::invoke_result_t<Fn, typename std::invoke_result_t<typename Iterator::operator*>> not compiling??
^
/Users/adam/school/cpp/invertedindex/inverted_index.hpp:61:127: error: expected unqualified-id before '{' token
In file included from /Users/adam/school/cpp/invertedindex/main.cpp:203:0: