Подтвердить что ты не робот

С++ 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. Каким должен быть тип?

4b9b3361

Ответ 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 или эквивалент.