_nn_:
__>Что говорит стандарт (который еще не вышел) насчет этого :
__>
auto f0 = [](int x) { return [=](int y) { return x + y; }; };
__>VC выдает: __>
error C3499: a lambda that has been specified to have a void return type cannot return a value
5.1.2/4:
If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type:
— if the compound-statement if of the form
{ return attribute-specifier opt expression ; }
the type of the returned expression after lvalue-to-rvalue conversion (4.1), array-to-pointer conversion
(4.2), and function-to-pointer conversion (4.3);
— otherwise, void.
Видимо, VC++ не прав. Похоже, он почему-то не считает lambda-выражение за выражение. На всякий случай попробуй обрамить внутреннее lambda-выражение круглыми скобочками — может, это заставит его передумать
remark:
R>Может что-то типа такого попробовать: R>
auto f1 = [](int x) -> decltype([=](int y) {}) { return [=](int y) { return x + y; }; };
Так точно не должно работать. Lambda-выражения не могут встречаться в операнде decltype:
5.1.2/2:
A lambda-expression shall not appear in an unevaluated operand (Clause 5).
Кроме того, типы даже одинаковых lambda-выражений уникальны:
5.1.2/3:
The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed nonunion class type — called the closure type — whose properties are described below.
#include <iostream>
#include <typeinfo>
int main()
{
auto f1 = [](int) { return 1;};
auto f2 = [](int) { return 1;};
std::cout << int(typeid(f1) == typeid(f2)) << std::endl;
// должен быть выведен 0
}
M>Так точно не должно работать. Lambda-выражения не могут встречаться в операнде decltype:
Исходя из того, что они должны иметь уникальные типы, это вполне логичное требование
Да, это ("decltype([=](int y) {})") было определенно глупо, тип по-любому будет засисеть от закапчуренных переменных (а тут ещё дополнительное требование, что он уникальный).
Проверил на студии, она действительно генерит уникальные типы. И то хорошо, у меня почему-то было ощущение, что она для одинаковых лямбд сгенерит одинаковый тип, и у нас будет ещё одно кривое различие в компиляторах на ближайшие 10 лет Но она всё равно отличилась, на "typeid(x1) == typeid(x2)" сказала "binary '==' : 'const type_info' does not define this operator or a conversion to a type acceptable to the predefined operator".
Здравствуйте, _nn_, Вы писали:
__>Здравствуйте, _nn_, Вы писали:
__>Ура ! Получилось
__>
__>#include <functional>
__>
__>Осталось узнать насколько законно это делать. __>Походу баг этот в VC2010 не исправят сегодня.
извините, а это что за брэйнфак такой?
вроде синтаксис отдаленно плюсы напоминает......
А как это std::function в конструктор лямбду принимает?Пробовал пройтись дебаггером — помоему хак.Кроме этого сам объект больше 20 байт что в gcc,что в msvc.А хотелось бы что-нибудь вида lambda<int()> нормального размера.Понятно что std::function расчитан на все случаи жизни и это не могло не сказаться на размерах объекта,но sizeof(lambda) что в gcc,что в msvc — 1 байт.Но кажется лямбды нельзя пихать в sizeof,хотя можно предположить что это индекс в таблице указателей на них.Кто что думает?Пускай даже тоже хак.
Здравствуйте, dipso, Вы писали:
D>А как это std::function в конструктор лямбду принимает?Пробовал пройтись дебаггером — помоему хак.Кроме этого сам объект больше 20 байт что в gcc,что в msvc.А хотелось бы что-нибудь вида lambda<int()> нормального размера.Понятно что std::function расчитан на все случаи жизни и это не могло не сказаться на размерах объекта,но sizeof(lambda) что в gcc,что в msvc — 1 байт.Но кажется лямбды нельзя пихать в sizeof,хотя можно предположить что это индекс в таблице указателей на них.Кто что думает?Пускай даже тоже хак.
boost::function у вас вопрос не вызывает ?
std/boost::function принимает в шаблоне прототип функции и таким образом знает сколько надо максимум выделить памяти для передачи всех аргументов.
int main()
{
auto x = []() { return 1; };
std::function<int(void)> xx(x);
}
Аналогично
int f() { return 1; }
int main()
{
int (*x)() = &f;
boost::function<int(void)> xx(x);
}
Здравствуйте, Masterkent, Вы писали:
M>_nn_:
__>>Осталось узнать насколько законно это делать.
M>УК РФ, Статья 273. Создание, использование и распространение вредоносных программ для ЭВМ. M>Срок до семи лет.
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. The value returned by this conversion function shall be the address of a function
that, when invoked, has the same effect as invoking the closure type’s function call operator.
[](int x) -> int может привестись к int(*)(int).
Следовательно может код даже законен ?
__> 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. The value returned by this conversion function shall be the address of a function
__> that, when invoked, has the same effect as invoking the closure type’s function call operator.
__>[](int x) -> int может привестись к int(*)(int). __>Следовательно может код даже законен ?
В том коде, что с reinterpret_cast, однозначное undefined behavior. Вот такой результат тебя устроит?
Здравствуйте, Masterkent, Вы писали:
__>>[](int x) -> int может привестись к int(*)(int). __>>Следовательно может код даже законен ?
M>В том коде, что с reinterpret_cast, однозначное undefined behavior.
Это понятно.
M>Вот такой результат тебя устроит?
Да уж. UB оно UB.
Остается только ждать фикса бага.
Кстати, как оказалось в VC есть оптимизация для std::function.
А это означает, что проблема решается просто и эффективно.