Ответ 1
В VС++ 2012 компилятор автоматически выбирает преобразование для безстоящих lambdas (у которого нет переменных захвата), когда вы конвертируете "неактивный lambda в указатель функции".
Лямбда
[...] Кроме того, в Visual С++ в Visual Studio 2012 без учета состояния lambdas конвертируются в указатели на функции. [...] (Visual С++ в Visual Studio 2012 еще лучше, потому что мы превратили безгарантийный lambdas конвертируемый в указатели функций, которые имеют условные условные соглашения. Это важно, когда вы используете API, которые ожидают такие вещи, как
__stdcall
указатели функций.)
Редакция:
NB: Вызывающее преобразование выходит за пределы С++ Standard, оно зависит от другой спецификации, такой как платформа ABI (двоичный интерфейс приложения).
Следующие ответы основаны на выходном ассемблерном коде с параметром /FAs. Так что это просто догадка, и, пожалуйста, попросите Microsoft более подробно: P
Q1. Что называется вызывающим соглашением лямбда-функции С++?
Q3. Если соглашение о вызове не определено, как правильно утилизировать пространство стека после вызова лямбда-функции?
Прежде всего, С++ lambda (-expression) НЕ является функцией (или указателем функции), вы можете вызвать operator()
на лямбда-объект, как нормальная функция вызова.
И код сборки сборки говорит, что VС++ 2012 генерирует лямбда-тело с преобразованием вызова __thiscall
.
Q2. Как указать вызывающее соглашение для функции лямбда С++?
AFAIK, нет способа. (Это может быть только __thiscall
)
Q4. Компилятор автоматически генерирует несколько версий лямбда-функции? то есть в виде следующего псевдокода: [...]
Возможно, нет.
Лямбда-тип VС++ 2012 обеспечивает только одну реализацию лямбда-тела (void operator()()
), но предоставляет множественное "определяемое пользователем преобразование в указатель функции" для каждого преобразования вызова (указатель функции возврата оператора с void (__fastcall*)(void)
, void (__stdcall*)(void)
и void (__cdecl*)(void)
).
Вот пример:
// input source code
auto lm = [](){ /*lambda-body*/ };
// reversed C++ code from VC++2012 output assembly code
class lambda_UNIQUE_HASH {
void __thiscall operator()() {
/* lambda-body */
}
// user-defined conversions
typedef void (__fastcall * fp_fastcall_t)();
typedef void (__stdcall * fp_stdcall_t)();
typedef void (__cdecl * fp_cdecl_t)();
operator fp_fastcall_t() { ... }
operator fp_stdcall_t() { ... }
operator fp_cdecl_t() { ... }
};
lambda_UNIQUE_HASH lm;