С++ 0x lambda, как я могу пройти в качестве параметра?
Пожалуйста, просмотрите следующий код, связанный с лямбдой, С++ 0x:
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
. Каким должен быть тип?
Ответы
Ответ 1
Преобразование в указатель функции относительно новое: оно было введено с 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; });
Ответ 2
Если вы действительно настаиваете на том, чтобы не использовать function<>
, тогда вы, вероятно, могли бы использовать decltype:
typedef decltype([](void*)->uint_64{return 0;}) my_lambda_type;
Я действительно не рекомендую это, потому что вы решительно ограничиваете себя, и я даже не знаю, гарантировано ли то, что две лямбды с одной и той же подписью будут одного и того же типа.
Ответ 3
Попробуйте (не тестировалось):
#include <function>
typedef std::function< int64_t (void*) > weight_func;
typedef std::map<std::string, weight_func > CallbackTable;
Я не думаю, что есть другой способ сделать это, чем использовать std:: function или эквивалент.