Как создать экземпляр типа лямбда-замыкания в C ++ 11/14? - PullRequest
10 голосов
/ 01 июня 2019

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

Рассмотрим следующий минимальный пример :

#include <iostream>

template <typename FuncType>
std::pair<int,int> DoSomething() {
    return FuncType()(std::make_pair(1,1));
}

int main() {
    auto myLambda = [](std::pair<int,int> x) {
        return std::make_pair(x.first*2,x.second*2);
    };
    std::pair<int,int> res = DoSomething<decltype(myLambda)>();
    return 0;
}

Из соображений производительности Я не могу использовать std::function, чтобы избежать вызовов виртуальных указателей. Есть ли способ сделать это? Мне нужно один раз создать экземпляр этой лямбды и использовать ее много раз внутри этой функции.

Как стандартная библиотека работает, когда decltype(myLambda) передается в нечто вроде std::map компараторов в параметре шаблона?

Ответы [ 3 ]

7 голосов
/ 01 июня 2019

Хотя эта функция появилась в C ++ 20 (см. Ответ songyuanyao), в этом случае она вам на самом деле не нужна.Вы можете просто передать лямбду как параметр функции типа FuncType и вызвать его несколько раз:

template <typename FuncType>
std::pair<int,int> DoSomething(FuncType f)
{
    return f(std::make_pair(1,1));
}

int main()
{
    auto myLambda = [](std::pair<int,int> x) {
        return std::make_pair(x.first*2,x.second*2);
    };
    std::pair<int,int> res = DoSomething(myLambda);
}
5 голосов
/ 01 июня 2019

Я знаю, что не существует конструктора по умолчанию для типа лямбда-замыкания.

Да, это так до C ++ 20. (Обратите внимание, что, поскольку C ++ 20, если захват не указан, тип закрытия имеет конструктор по умолчанию по умолчанию.)

Типы закрытия не являются DefaultConstructible. Типы замыканий имеют конструктор по умолчанию a deleted (until C++14) no (since C++14). (до C ++ 20)

И

Как стандартная библиотека работает, когда decltype(myLambda) передается в нечто вроде std::map компараторов в параметре шаблона?

В стандартной библиотеке нет ничего особенного. Если в качестве типа компаратора для std::map вы указали не-DefaultConstructible лямбду, вы должны передать объект конструктору, std::map инициализирует его компаратор с помощью copy; У лямбды есть конструктор копирования и перемещения.

Вы можете изменить свой код так же, как конструктор std::map :

template <typename FuncType>
std::pair<int,int> DoSomething(const FuncType& f = FuncType()) {
    // auto z(f);   // you can take a copy if necessary
    return f(std::make_pair(1,1));
}

тогда

auto myLambda = [](std::pair<int,int> x) {
    return std::make_pair(x.first*2,x.second*2);
};
std::pair<int,int> res = DoSomething<decltype(myLambda)>(myLambda);

ЖИТЬ

2 голосов
/ 02 июня 2019

Как отмечали другие, пустые лямбды станут конструируемыми по умолчанию в C ++ 20.

Вы не можете ждать / переключиться на него?
Нет проблем, это легко эмулируется, покаваша лямбда не является универсальной.

Просто преобразуйте лямбду в указатель функции и упакуйте ее в std::integral_constant:

template <class T>
constexpr auto make_constant(T t) noexcept
-> std::integral_constant<decltype(+t), +t>
{ return {}; }

Конечно, в большинстве случаев, когда вы можетевыберите тип объекта-функции, вы также можете передать начальное значение, что немного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...