C++ 0x

Jan 12, 2011 21:02

Текущий вариант стандарта выглядит гораздо более вменяемым, чем то, что нам показывали пару лет назад. Вместо фантазий на тему "как нам сделать из шаблонов настоящий пацанский compile-time Haskell" видим решения изрядно подзадолбавших проблем и некоторое количество легко имплементируемых и вполне приятных (хотя и совершенно необязательных) бантиков ( Read more... )

soft

Leave a comment

ban_dana January 12 2011, 18:24:54 UTC
А чем плохи лямбды? Довлоьно удобная вещь, вроде бы (ну, если без фанатизма, конечно)....

Reply

plakhov January 12 2011, 18:36:34 UTC
Ну в общем если на них смотреть не с точки зрения парадигм функционального программирования, а с точки зрения "старого" С++, то это просто такой синтаксический сахар для временных объектов, предназначенных к использованию с STL-like алгоритмами, который легко абьюзить, и, кажется, дико нетривиальный для имплементации в компиляторе (может быть, я ошибаюсь - я не писал компиляторы плюсов). Ох, боюсь, что лямбды в стандарте задержат появление полноценных С++0х компиляторов на несколько месяцев. По-моему, поддержать compile-time reflection стоило бы меньше усилий, а толку на порядки больше.

Reply

zhengxi January 12 2011, 18:45:04 UTC
Лямбды как раз уже сделаны и с gcc и в msvc.
В отличие от range for, variadic templates (нет в msvc) и nullptr (нет в gcc 4.5)

Reply

plakhov January 12 2011, 18:53:32 UTC
Ну может быть. Я, если честно, видел только []-лямбды, т.е. с тривиальными временными объектами. Работают ли всякие извращения в capture list'ах вроде [=x,&y]{...}, я не знаю. Очень подозреваю, что вылизывать баги во всём этом будут еще долго.

Насчет второй части - range for по сути всего лишь макрос, чего его там имплементировать, nullptr вообще тривиален
variadic templates - в конце концов, хрен с ними, не очень-то хочется

Reply

_winnie January 12 2011, 19:37:18 UTC
А что там такого с багами в лямбдах. это трансформация чуть ли не на уровне шаблонов IDE или regexp.

Гораздо интересней будет когда эти лямбды будут абъющить не для линейного поиска в векторе, а для делегатов/подписок, вот тогда действительно будут портить стек очень часто.

Reply

plakhov January 12 2011, 19:47:04 UTC
Например, прикинь себе логику компиляции лямбды с capture-list'ом [&] так, чтобы не было лишних накладных расходов. Что там с ними как с first class object'ами, как их хранят-передают-возвращают-swap'ают-whatever. Как их тип манглируется. Не успел пока почитать, что там у них с областями видимости, с доступом к this и к глобальным переменным - если есть, то там с учетом всех прелестей ООП такого можно наворотить, что просто дух захватывает.

Reply

_winnie January 12 2011, 20:04:04 UTC
> Например, прикинь себе логику компиляции лямбды с capture-list'ом [&] так, чтобы не было лишних накладных расходов.
Вроде оптимизация "не захватывать то, что не используется" выглядит очевидной. Ну есть же наверное список свободных параметров у компиляторо-писателей. Хотя бы для того, что бы синтаксис проверить, что не используются неопределённые переменные.

Что там с ними как с first class object'ами, как их хранят-передают-возвращают-swap'ают-whatever.
Если представить захват переменной по ссылке как указатель в объекте-предикате, а по значению - просто как член, то всё выглядит довольно привычным. И грабли сразу понятно какие - копирование по значению сложных структур данных, захват по ссылке локальных переменных при использовании лямбды как значение функции.

this - это просто константный указатель, можно считать что это неявно объявленная локальная переменная.

Reply

bik_top January 12 2011, 21:41:39 UTC
> Если представить захват переменной по ссылке как указатель в объекте-предикате...

В C# наоборот: не указатель в объекте-замыкании ссылается на локальную переменную, а «захватываемая локальная переменная» по сути ссылается на член в объекте-замыкании.

Т.е. (условно говоря в терминах текущих возможностей C++) для решения подобной задачи используется не первый подход, а второй.

Reply

_winnie January 12 2011, 22:04:56 UTC
Посмотрел как на самом деле в С++0x.
Действительно, внутренности лямбды оказались предсказуемыми. Лябмда которая определена как ([x,&y] { y += x; }) - размером в восемь байт под VC++/Win32. Состоит из значения x (int) и указателя на y.

//#include
#include

template
void dump_object(const F &f)
{
const unsigned char *pc = reinterpret_cast(&f);
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

bik_top January 12 2011, 22:34:54 UTC
У тебя там (по крайней мере) один два const'а пропущено :)

> Действительно, внутренности лямбды оказались предсказуемыми. Лябмда... состоит из значения x (int) и указателя на y.

Я когда-то это косвенно проверял - возвращал замыкание из функции и убеждался, что оно ссылается на пямять, перезатёртую стек-фреймом другой функции. (Т.е. восходящая funarg-проблема не решена.)

Замыкания в C++ нельзя реализовать как синт. сахар над вторым вариантом. Видимо, потому что требуется (не уверен только, кому и зачем), чтобы определение локальной переменной «int x = 10;» всегда означало тупую стековую переменную, а не поле скрытого класса. Так что остаётся первый неполноценный вариант.

А в C# проще. Написал «int x = 10;» - она у тебя стековая, где-то позже замкнул - стала «кучевая» (в составе анонимного объекта-замыкания). Тоже проблемы есть, если нужно dispose'ить замкнутые объекты. (Память-то сборщик разрулит, а другие ресурсы кто освобождать будет?)

Reply

_winnie January 13 2011, 08:39:46 UTC
>У тебя там (по крайней мере) один два const'а пропущено :)
А где?

>(Т.е. восходящая funarg-проблема не решена.)
Ну, всякие int-переменные можно по значению копировать.

Можно и большие структуры данных держать по умному указателю, правда это путь к тому, что перестаёшь понимать как программа использует память (впрочем, это касается и функциональных языков).

Reply

bik_top January 13 2011, 08:48:29 UTC
>> У тебя там (по крайней мере) один два const'а пропущено :)
> А где?

const unsigned char * const pc = ...
...
auto const f = ([x,&y] { y += x; });
> Можно и большие структуры данных держать по умному указателю

Дело ж не в «больших», а в том, что при завхвате локальной переменной по ссылке, она уже не может быть стековой, а должна размещаться в динамической памяти.

Reply

ext_38945 January 12 2011, 21:24:57 UTC
>Работают ли всякие извращения

Смотрела gcc, VC++, Intel C++

Лямбды в целом работают, ошибки и странности есть, их быстро фиксят.

Диагностика ошибок вменяемая, но могла бы быть и лучше.

Reply

plakhov January 12 2011, 19:06:20 UTC
Перечитал пост; судя по комментариям, в нем содержится двусмысленность. Уточню: тэгом "ересь" обозначена не сама фича, а как раз моё к ней отношение. Я и сам отлично понимаю, что оно как минимум спорное.

Reply


Leave a comment

Up