Получить тип возврата лямбда-выражения - PullRequest
0 голосов
/ 22 января 2019

Я занимаюсь разработкой итератора C ++, который оценивает лямбда-выражение при каждой разыменовании итератора.

Таким образом, я реализовал пользовательский класс итератора и перегрузил оператор разыменования, чтобы он выполнял лямбда-выражение для каждой разыменования, таким образом я могу поместить нужное мне выражение в функцию лямбда-выражения.

Все работает нормально, но это не типо-типично, потому что в строке 9 в коде ниже я предполагаю, что лямбда-выражение вернет значение double. Как я могу получить тип возврата лямбда? Я пытался std::result_of<Lambda>, но это не сработало.

Вот код, который я написал:

#include <iostream>
#include <vector>
#include <utility>
#include <cmath>

template <class Iterator, class Lambda>
struct LambdaIterator: Iterator {
public:
    using value_type = double; // <--- How do I get the return type of the lambda?

    LambdaIterator(Iterator&& begin, Lambda&& lambda) :
        Iterator(std::forward<Iterator>(begin)),
        lamdaexpr(std::forward<Lambda>(lambda)) {}

    value_type operator*() {
        return lamdaexpr(*static_cast<Iterator&>(*this));
    }
private:
    Lambda lamdaexpr;
};

// Helper function, only needed to easily instantiate the iterator
template <class Iterator, class Lambda>
LambdaIterator<Iterator, Lambda> MakeLambdaIterator(Iterator&& begin, Lambda&& lambda) {
    return {std::forward<Iterator>(begin), std::forward<Lambda>(lambda)};
}

template<class BeginIterator, class EndIterator>
typename BeginIterator::value_type Sum(BeginIterator begin, EndIterator end) {
    typename BeginIterator::value_type sum = 0;

    while (begin != end) {
        sum += *begin;
        begin++;
    }
    return sum;
}

int main() {
    std::vector<double> vec;
    for (int i = 0; i < 10; i++)
        vec.push_back(i); // Puts some data into the vector

    std::cout << Sum(vec.begin(), vec.end()) << std::endl; // Works fine
    std::cout << Sum(MakeLambdaIterator(vec.begin(),
                     [](double item) -> double { // Works as long as it returns a double
                        return sqrt(item); // Prints the sum of the square roots
                     } ), vec.end()) << std::endl;
    std::cout << Sum(MakeLambdaIterator(vec.begin(),
                     [](double item) -> double {
                        return pow(item, 2); // Prints the sum of the squares
                     } ), vec.end()) << std::endl;
}

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Как мне получить тип возврата лямбды?

Учитывая, что вы знаете тип аргумента, мне кажется, что вы ищете исполнение внутри decltype().

Я имею в виду что-то как

using value_type = decltype( std::declval<Lambda>()(*std::declval<Iterator>()) );

Это также работает с универсальной лямбдой.

Не по теме: если вы хотите использовать прямую семантику для конструктора LambdaIterator(), вы должны преобразовать ее в шаблон, чтобы иметь && в качестве универсальной ссылки вместо ссылки на r-значение.

Я имею в виду: вы должны написать следующее

  template <typename I, typename L>
  LambdaIterator (I && begin, L && lambda)
     : Iterator{std::forward<I>(begin)}, lamdaexpr{std::forward<L>(lambda)}
     { }
0 голосов
/ 22 января 2019

Есть несколько способов, как вы можете достичь этого, простейшие из следующих:

decltype(auto) operator*() {
    return lamdaexpr(*static_cast<Iterator&>(*this));
}
...