Съемная лямбда не может быть преобразована в указатель функции при сохранении в std:: function

Обычно, лямбда С++ без захвата должна быть преобразована в указатель функции c-стиля. Как бы то ни было, преобразование его с помощью std::function::target не работает (т.е. Возвращает nullptr), также target_type не соответствует типу подписи, даже если он кажется одинаковым.

Протестировано на VC13 и GCC 5.3/5.2.0/4.8

Пример минимального тестирования:

#include <functional>
#include <iostream>

void Maybe() {

}

void callMe(std::function<void()> callback) {
    typedef void (*ftype)();
    std::cout << (callback.target_type() == typeid(ftype)) << std::endl;
    std::cout << callback.target<ftype>() << std::endl;
}

int main() {
    callMe([] () {});
    callMe(Maybe);
}

ожидаемый результат будет

1
<address>
1
<address>

фактический вывод

0
0
1
<address>

Возникает вопрос: почему лямбда-подпись отличается от переданной функции?

Ответы

Ответ 1

В вашем первом вызове std::function не беспокоит разложение лямбда на указатель, он просто сохраняет его с его фактическим типом (который действительно не является void()).

Вы можете заставить лямбда распадаться на указатель перед конструированием std::function с помощью последнего, просто используя унарный +:

callMe(+[](){});
//     ^