Текущий вариант стандарта выглядит гораздо более вменяемым, чем то, что нам показывали пару лет назад. Вместо фантазий на тему "как нам сделать из шаблонов настоящий пацанский compile-time Haskell" видим решения изрядно подзадолбавших проблем и некоторое количество легко имплементируемых и вполне приятных (хотя и совершенно необязательных) бантиков
(
Read more... )
Reply
Reply
В отличие от range for, variadic templates (нет в msvc) и nullptr (нет в gcc 4.5)
Reply
Насчет второй части - range for по сути всего лишь макрос, чего его там имплементировать, nullptr вообще тривиален
variadic templates - в конце концов, хрен с ними, не очень-то хочется
Reply
Гораздо интересней будет когда эти лямбды будут абъющить не для линейного поиска в векторе, а для делегатов/подписок, вот тогда действительно будут портить стек очень часто.
Reply
Reply
Вроде оптимизация "не захватывать то, что не используется" выглядит очевидной. Ну есть же наверное список свободных параметров у компиляторо-писателей. Хотя бы для того, что бы синтаксис проверить, что не используются неопределённые переменные.
Что там с ними как с first class object'ами, как их хранят-передают-возвращают-swap'ают-whatever.
Если представить захват переменной по ссылке как указатель в объекте-предикате, а по значению - просто как член, то всё выглядит довольно привычным. И грабли сразу понятно какие - копирование по значению сложных структур данных, захват по ссылке локальных переменных при использовании лямбды как значение функции.
this - это просто константный указатель, можно считать что это неявно объявленная локальная переменная.
Reply
В C# наоборот: не указатель в объекте-замыкании ссылается на локальную переменную, а «захватываемая локальная переменная» по сути ссылается на член в объекте-замыкании.
Т.е. (условно говоря в терминах текущих возможностей C++) для решения подобной задачи используется не первый подход, а второй.
Reply
Действительно, внутренности лямбды оказались предсказуемыми. Лябмда которая определена как ([x,&y] { y += x; }) - размером в восемь байт под VC++/Win32. Состоит из значения x (int) и указателя на y.
//#include
#include
template
void dump_object(const F &f)
{
const unsigned char *pc = reinterpret_cast
for (int i = 0; i < sizeof(f); ++i)
printf("%02x ", (unsigned int)pc[i]);
printf("\n");
}
int main()
{
int x = 10;
int y = 20;
auto f = ([x,&y] { y += x; });
x = 50;
f();
//std::cout << x << " " << y << '\n';
dump_object(f);
dump_object(x);
dump_object(&y);
}_Winnie C++ Colorizer
0a 00 00 00 74 ff 12 00 - лябмда
32 00 00 00 - значение x
74 ff 12 00 - указатель на y
PS. переприсволил в x=10 новый x=50, поэтому во второй строке "32 00 00 00" а не "0a 00 00 00"
Reply
> Действительно, внутренности лямбды оказались предсказуемыми. Лябмда... состоит из значения x (int) и указателя на y.
Я когда-то это косвенно проверял - возвращал замыкание из функции и убеждался, что оно ссылается на пямять, перезатёртую стек-фреймом другой функции. (Т.е. восходящая funarg-проблема не решена.)
Замыкания в C++ нельзя реализовать как синт. сахар над вторым вариантом. Видимо, потому что требуется (не уверен только, кому и зачем), чтобы определение локальной переменной «int x = 10;» всегда означало тупую стековую переменную, а не поле скрытого класса. Так что остаётся первый неполноценный вариант.
А в C# проще. Написал «int x = 10;» - она у тебя стековая, где-то позже замкнул - стала «кучевая» (в составе анонимного объекта-замыкания). Тоже проблемы есть, если нужно dispose'ить замкнутые объекты. (Память-то сборщик разрулит, а другие ресурсы кто освобождать будет?)
Reply
А где?
>(Т.е. восходящая funarg-проблема не решена.)
Ну, всякие int-переменные можно по значению копировать.
Можно и большие структуры данных держать по умному указателю, правда это путь к тому, что перестаёшь понимать как программа использует память (впрочем, это касается и функциональных языков).
Reply
> А где?
const unsigned char * const pc = ...
...
auto const f = ([x,&y] { y += x; });
> Можно и большие структуры данных держать по умному указателю
Дело ж не в «больших», а в том, что при завхвате локальной переменной по ссылке, она уже не может быть стековой, а должна размещаться в динамической памяти.
Reply
Смотрела gcc, VC++, Intel C++
Лямбды в целом работают, ошибки и странности есть, их быстро фиксят.
Диагностика ошибок вменяемая, но могла бы быть и лучше.
Reply
Reply
Leave a comment