Подтвердить что ты не робот

Автовыделение типа аргумента и анонимные лямбда-функции

Предположим, что у меня есть эти строки кода;

std::vector<int> ints;
std::for_each(ints.begin(), ints.end(), [](int& val){ val = 7; });

Однако я не хочу указывать тип аргумента в моих лямбда-функциях, т.е. я хочу написать что-то вроде этого:

std::for_each(ints.begin(), ints.end(), [](auto& val){ val = 7; });

В любом случае это может быть достигнуто?

(boost:: lambda не требует типов, которые нужно указать...)


Update:

Теперь я использую макрос: #define _A(container) decltype(*std::begin(container)), чтобы я мог:

std::for_each(ints.begin(), ints.end(), [](_A(ints)& val){ val = 7; });
4b9b3361

Ответ 1

Нет. "Полиморфные лямбды" - это то, о чем эта функция упоминалась во время обсуждения в комитете С++, и она не была стандартизирована. Необходимо указать типы параметров лямбда.

Вы можете использовать decltype, хотя:

std::for_each(ints.begin(), ints.end(), [](decltype(*ints.begin())& val){ val = 7; });

Ответ 2

Ваш предпочтительный синтаксис является допустимым с С++ 14 и упоминается как универсальная лямбда или полиморфная лямбда.

http://isocpp.org/blog/2013/04/n3649-generic-polymorphic-lambda-expressions-r3

auto lambda = [](auto x) { return x; };
lambda(5);
lambda("hello");
lambda(std::vector<int>({5, 4, 3}));

Начиная с С++ 20, мы также можем использовать этот синтаксис для обычных функций:

auto f(auto x) { return x; }

Ответ 3

Если у вас есть контейнер, вы можете попробовать что-то вроде этого

template<typename Container>
void reset(Container c)
{
   for_each(c.begin(),c.end(),[](typename Container::reference val) { val=7; });
}

Ответ 4

Попробуйте следующее:

#include <functional>
#include <algorithm>
#include <iostream>

template <typename ValTy>
std::function<void(ValTy&)> polymorphicLambda ()
{
    return std::function<void(ValTy&)> ([](ValTy& val) -> void { val = 7; } );
}

int main()
{
    std::vector<int> ints(5);

    std::generate_n(ints.begin(), 5, []() { return 0; });
    std::for_each(ints.begin(), ints.end(), [](int& val) { std::cout << val << "\t"; });
    std::cout << std::endl;

    std::for_each(ints.begin(), ints.end(), polymorphicLambda<int>());
    std::for_each(ints.begin(), ints.end(), [](int& val) { std::cout << val << "\t"; });
    std::cout << std::endl;


    std::vector<double> doubles(5);

    std::generate_n(doubles.begin(), 5, []() { return 0; });
    std::for_each(doubles.begin(), doubles.end(), [](double& val) { std::cout << val << "\t"; });
    std::cout << std::endl;

    std::for_each(doubles.begin(), doubles.end(), polymorphicLambda<double>());
    std::for_each(doubles.begin(), doubles.end(), [](double& val) { std::cout.precision(2); std::cout << std::fixed << val << "\t"; });
    std::cout << std::endl;

    return 0;
}

Возможно, вы также сможете создавать фанки с lambdas, которые не возвращают void, а также с вариативными шаблонами, которые передаются в несколько параметров для lambda.