Использование адаптеров Boost с С++ 11 lambdas
Я попытался скомпилировать этот код:
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>
int main() {
std::vector<int> v{
1,5,4,2,8,5,3,7,9
};
std::cout << *boost::min_element(v | boost::adaptors::transformed(
[](int i) { return -i; })) << std::endl;
return 0;
}
Ошибка компиляции со следующим сообщением об ошибке (после длинного шаблона создания шаблона):
/usr/local/include/boost/iterator/transform_iterator.hpp:84:26: error: use of deleted function ‘main()::<lambda(int)>::<lambda>()’
../main.cpp:12:5: error: a lambda closure type has a deleted default constructor
Я искал проблему и нашел этот в архиве списка рассылки Boost Users. Он предположил, что использование #define BOOST_RESULT_OF_USE_DECLTYPE
решит проблему. Я положил его в начало моего кода, но он все еще не компилируется. Длина сообщения об ошибке кажется намного короче, но сообщение об ошибке в конце одного и того же. В настоящее время я использую Boost 1.50.
В чем может быть проблема? Есть ли способ сделать эту работу?
Ответы
Ответ 1
http://smellegantcode.wordpress.com/2011/10/31/linq-to-c-or-something-much-better/
Но вы можете использовать это, что хорошо работает.
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <vector>
#include <functional>
int main() {
std::vector<int> v{
1,5,4,2,8,5,3,7,9
};
std::function<int(int)> func = [](int i) { return -i; };
std::cout << *boost::min_element(v | boost::adaptors::transformed(
func)) << std::endl;
return 0;
}
http://liveworkspace.org/code/b78b3f7d05049515ac207e0c12054c70
#define BOOST_RESULT_OF_USE_DECLTYPE
работает отлично в VS2012, например.
Ответ 2
Вы можете превратить не-захватывающий лямбда в указатель на функцию, поставив перед ним "+".
std::vector<int> v{1,5,4,2,8,5,3,7,9};
std::cout << *boost::min_element(v |
boost::adaptors::transformed(+[](int i)
{
return -i;
})) << std::endl;
Ответ 3
Это описано в http://boost.2283326.n4.nabble.com/range-cannot-use-lambda-predicate-in-adaptor-with-certain-algorithms-td3560157.html и https://svn.boost.org/trac/boost/ticket/4189 - проблема в том, что некоторые алгоритмы ожидают, что они смогут скопировать-построить (и по умолчанию-построить и скопировать-присваивать) свой предикат, который не может быть выполнен с помощью лямбда.
Обходной путь состоит в том, чтобы обернуть лямбда в std::function
:
*boost::min_element(
v | boost::adaptors::transformed(std::function<int(int)>(
[](int i) { return -i; })));
Я попросил (at вызывать подпись вызова лямбда или произвольно вызываемого для "make_function" для способа записи a make_function
такой, что можно просто написать:
*boost::min_element(
v | boost::adaptors::transformed(make_function(
[](int i) { return -i; })));