C++0x лямбда, как я могу передать в качестве параметра?
Пожалуйста, посмотрите на следующий код, связанный с C++0x lambda:
typedef uint64_t (*WEIGHT_FUNC)(void* param);
typedef std::map<std::string, WEIGHT_FUNC> CallbackTable;
CallbackTable table;
table["rand_weight"] = [](void* param) -> uint64_t
{
return (rand() % 100 + 1);
};
Я получил ошибку (в Visual Studio 2010), что лямбда не может быть преобразована в тип WEIGHT_FUNC
, Я также знаю ответ: с помощью std::function object
:
typedef std::function<uint64_t (void*)> WEIGHT_FUNC;
Тем не менее, я также хочу знать, как я могу получить тип лямбда без использования std::function
, Какого типа это должно быть?
3 ответа
Преобразование в указатель на функцию является относительно новым: оно было введено с N3043 15 февраля 2010 года.
Хотя, например, GCC 4.5 реализует его, Visual Studio 10 был выпущен 12 апреля 2010 года и, таким образом, просто не реализовал его вовремя. Как указал Джеймс, это будет исправлено в будущих выпусках.
На данный момент вы должны использовать одно из альтернативных решений, представленных здесь.
Технически, что-то вроде следующего обходного пути будет работать, но без шаблонов с переменными числами его не интересно обобщать (Boost.PP на помощь...), и нет никакой защитной сетки от передачи лямбд в:
typedef uint64_t (*WeightFunc)(void* param);
template<class Func> WeightFunc make_function_pointer(Func& f) {
return lambda_wrapper<Func>::get_function_pointer(f);
}
template<class F> class lambda_wrapper {
static F* func_;
static uint64_t func(void* p) { return (*func_)(p); }
friend WeightFunc make_function_pointer<>(F& f);
static WeightFunc get_function_pointer(F& f) {
if (!func_) func_ = new F(f);
return func;
}
};
template<class F> F* lambda_wrapper<F>::func_ = 0;
// ...
WeightFunc fp = make_function_pointer([](void* param) -> uint64_t { return 0; });
Если вы действительно настаиваете на том, чтобы не использовать function<>
тогда вы можете использовать decltype:
typedef decltype([](void*)->uint_64{return 0;}) my_lambda_type;
Я действительно не рекомендую это, хотя, так как вы резко ограничиваете себя, и я даже не знаю, гарантированно ли два лямбда с одинаковой сигнатурой будут одного типа.
Попробуйте с (не проверено):
#include <function>
typedef std::function< int64_t (void*) > weight_func;
typedef std::map<std::string, weight_func > CallbackTable;
Я не думаю, что есть какой-либо другой способ сделать это, кроме как использовать std::function или эквивалентный.