int main()
{
int foo;
void (*fp)() = [&]{ foo = 0; }; // error: cannot convert 'main()::<lambda()>' to 'void (*)()' in initialization
}
int main()
{
int foo;
void (*fp)() = [&foo]{}; // error: cannot convert 'main()::<lambda()>' to 'void (*)()' in initialization
}
gcc 4.7.2.
По-моему, первый кусок кода также не должен был скомпилироваться.
ISO/IEC 14882:2011
5.1.2 Lambda expressions [expr.prim.lambda]
6 The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const
conversion function to pointer to function having the same parameter and return types as the closure type’s
function call operator.
Здравствуйте, Nikita.Trophimov, Вы писали:
NT>По-моему, первый кусок кода также не должен был скомпилироваться. NT>
NT>6 The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const
NT>conversion function to pointer to function having the same parameter and return types as the closure type’s
NT>function call operator.
Это же не причина. Из условия «все А обладают свойством Б» не следует, что свойством Б не могут обладать какие-либо третьи объекты.
Только этот пункт не запрещает приводить любые лямбды к указателям на функции, он лишь описывает для каких лямбд это приведение будет гарантированно успешным.
NT>Баг gcc?
А ещё такой же «баг» есть в msvc и в intel c++. Разве что clang решил отличится.
По-моему, тут нет запрета от стандарта. Так что на полноценный баг это не тянет. Но так как и гарантий тоже нет, то пользоваться этой особенностью не следует.
WM>Это же не причина. Из условия «все А обладают свойством Б» не следует, что свойством Б не могут обладать какие-либо третьи объекты. WM>Только этот пункт не запрещает приводить любые лямбды к указателям на функции, он лишь описывает для каких лямбд это приведение будет гарантированно успешным.
The closure type for a lambda-expression with no lambda-capture
Теперь смотрим на наш код:
int main()
{
void (*fp)() = [&]{};
}
lambda-capture присутствует, однако код компилируется.
Здравствуйте, Nikita.Trophimov, Вы писали:
WM>>Это же не причина. Из условия «все А обладают свойством Б» не следует, что свойством Б не могут обладать какие-либо третьи объекты. WM>>Только этот пункт не запрещает приводить любые лямбды к указателям на функции, он лишь описывает для каких лямбд это приведение будет гарантированно успешным.
NT>
NT>The closure type for a lambda-expression with no lambda-capture
NT>lambda-capture присутствует, однако код компилируется.
Всё верно. Почему он обязан не компилироваться? Приведи цитату, которая это запрещает. Указанный тобой до этого пункт 5.1.2.6 не подходит на эту роль, так как, во-первых, не содержит запрета вообще, а, во-вторых, не применим к данному коду (именно из-за выделенного тобой условия).
WM>Всё верно. Почему он обязан не компилироваться? Приведи цитату, которая это запрещает. Указанный тобой до этого пункт 5.1.2.6 не подходит на эту роль, так как, во-первых, не содержит запрета вообще, а, во-вторых, не применим к данному коду (именно из-за выделенного тобой условия).
Хорошо, давайте мыслить терминами стандарта языка. Итак, мы имеем фразу, разрешающую преобразование лямбды к указателю на функцию в том случае, если лямбда не содержит lambda-capture, а также функция имеет те же параметры и тип возвращаемого значения, как и лямбда. О других возможных преобразованиях ничего не сказано. Любой неописанный стандартом код является ill-formed, однако трансляция не обязана быть закончена, потому что для ill-formed программ требуется лишь выдача diagnostic message. Более того, реализация иметь предоставлять расширения, позволяющие транслировать ill-formed программы.