Я узнал, что лямбда и std::function — это разные типы. Я также знаю, что лямбду без захвата можно преобразовать в указатель на функцию. Но затем я написал следующую программу, которая компилируется с clang, но отклоняется gcc. Демо
#include <functional>
#include <iostream>
#include <string>
int func()
{
return 5;
}
int main()
{
std::function<const int&()> getter1 =
[] { return func(); }; //gcc rejects but clang accepts
getter1();
}
GCC говорит:
<source>: In function 'int main()':
<source>:12:41: error: conversion from 'main()::<lambda()>' to non-scalar type 'std::function<const int&()>' requested
12 | [] { return func(); }; //gcc rejects but clang accepts
| ^~~~~~~~~~~~~~~~~~~~~
Compiler returned: 1
Хотя msvc выдает предупреждение:
warning C4172: returning address of local variable or temporary
Compiler returned: 0
Прав ли gcc, отвергая программу, или clang, принимая ее?





gcc теперь правильно отклоняет код, начиная с P2255, в котором добавлен новый признак типа для определения того, когда ссылки привязаны к временным объектам.
Проблема с этим объявлением:
std::function<const int&()> getter1 = [] { return func(); };
в том, что getter1() — это безусловное неопределенное поведение.
Это точно аналогично этому случаю:
const int& oops() { return func(); }
Мы привязываем ссылку к временному int, который сразу же выходит за пределы области действия еще до того, как функция вернется, поэтому любая попытка чтения из ссылки не определена.
За исключением того, что компиляторы уже некоторое время предупреждали о oops, и только теперь у них появились инструменты, чтобы также предупреждать о getter1. И это здорово!
[] { return func(); }возвращаетint, так что, похоже, clang неправильный