Посмотрите на следующий C++ 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
. Каково тип это должно быть?
Преобразование в указатель на функцию является относительно новым: оно было введено в 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 или эквивалент.