Будет C++ 0x поддержка __ stdcall или экстерн “C” получение - ничто лямбды?

Вчера я думал о том, будет ли возможно использовать удобство C++ 0x функции лямбды для записи обратных вызовов для Windows API functions.

Например, что, если я хотел использовать лямбду в качестве EnumChildProc с EnumChildWindows? Что-то как:

EnumChildWindows(hTrayWnd, CALLBACK [](HWND hWnd, LPARAM lParam) {
        // ...
        return static_cast(TRUE); // continue enumerating
    }, reinterpret_cast(&myData));

Другое использование должно было бы записать extern "C" обратные вызовы для стандартных программ C. Например:

my_class *pRes = static_cast(bsearch(&key, myClassObjectsArr, myClassObjectsArr_size, sizeof(my_class), extern "C" [](const void *pV1, const void *pV2) {
        const my_class& o1 = *static_cast(pV1);
        const my_class& o2 = *static_cast(pV2);

        int res;
        // ...
        return res;
    }));

Действительно ли это возможно?

Я могу понять, что лямбды, которые получают переменные, никогда не будут совместимы с C, но, по крайней мере, кажется возможным мне, что получение - ничто лямбды может быть совместимым.

16
задан Johannes Schaub - litb 1 October 2011 в 13:59
поделиться

2 ответа

Лямбды без захвата неявно конвертируются в указатель на функцию (с помощью неявной функции преобразования, определяемой типом закрытия).

FCD, похоже, не указывает, какую языковую связь имеет тип функции этого указателя на функцию, так что если вам нужно передать этот указатель на функцию в функции Си, соглашение о вызове функций Си++ и функций Си должно быть одинаковым. Я полагаю, что в Windows это так и есть. Так что вы должны иметь возможность передавать лямбду в функции Windows API

typedef void(*callbackType)(void *userData);
extern "C" void someCFunction(callbackType callback);

int main() {
  someCFunction([](void *userData) { /* ... */ });
}

Формулировка FCD в 5.1.2/6:

Закрывающий тип для лямбда-выражения без лямбда-захвата имеет публичную невиртуальную неявную функцию преобразования const в указатель на функцию, имеющую те же типы параметров и возврата, что и оператор вызова функции закрывающего типа. Значение, возвращаемое этой функцией преобразования, должно быть адресом функции, которая при вызове имеет тот же эффект, что и вызов оператора вызова функции закрывающего типа.

Я думаю, что в окончательном варианте стандарта должно быть примечание, в котором говорится, что существует функция преобразования как в указатели функций связей Си, так и в указатели функций связей Си++, поскольку конвертируемость в указатели функций Си является одной из целей этой функциональности.

14
ответ дан 30 November 2019 в 22:23
поделиться

Нет особо веских причин, по которым это не следует распространять на захват лямбды. Это требует некоторой генерации динамического кода, но это не должно выходить за рамки остроумия разработчиков компиляторов, и это упростит взаимодействие со старыми API-интерфейсами C на несколько порядков - больше нет необходимости передавать параметры через нетипизированные void * (что не все API даже предлагают).

2
ответ дан 30 November 2019 в 22:23
поделиться