Согласен, ошибки компиляции при использовании шаблонов это то еще зло :)
По поводу кодогенерации, то в проекте она есть, принцип следующий: сначала генерируем тип шаблонами, затем вызываем специальную программку, которая выводит в .cpp файлы typeid( TGeneratedType ).name() в нужных местах, это одним махом раскрывает все метавызовы под отладкой жить становится значительно проще :)
Возможно, когда-нибудь я перейду таки на полноценную кодогенерацию в таких местах…
Вот чтоб от switch избавится, это и было написано :)
Если вы под субклассами понимаете агрегацию, то в данном случае это не работает, т.к. затраты на указатели становятся слишком большими (объектов, просто, много). В итоге получается большое дерево наследования, которым надо как-то управлять, чтобы не сойти с ума при попытке добавить туда еще что-то. :) При этом сильно экономиться память, т.к. одинаковых по конечному типу объектов много, и вся динамическая информация храниться в таблицах виртуальных функций (которые по одной штуке на тип).
Симуляция рисков страховых компаний методом Монте Карло.
Большие проекты симулируются несколько дней на нескольких компьютерах (уровня i7). Полученные данные хранятся внутри атомов (тех самых объектов) здоровенного гиперкуба. Количество атомов при некоторых условиях достигает 100-200 миллионов.
ООП хорошо работает с целыми объектами. Шаблоны позволяют конструировать целые объекты из множества ПРОСТЫХ «деталек». Отдельно взятые «детальки» (врапперы, стратегии) целым объектом считать нельзя, они лишь реализуют какую-то определенную деталь поведения объекта. Чтобы объекты из этих деталек собирались нормально, а не впадали в «панику» из-за того, что кто-то скрепил детальки не в том порядке, в котором нужно, и используется информация о типах.
С точки зрения фабрики динамика означает лишь одно: на этапе инициализации вычислений мы можем проанализировать, какая функциональность потребуется от того или иного объекта, используя шаблоны мы можем собрать объект из «деталек», который будет нести в себе только эту функциональность, в противном случае все объекты были бы монстрами, способными обработать множество ситуаций, платой за что является либо память либо производительность.
> Бред! Если в классе уже есть хотя бы один виртуальный метод, что автоматически подразумевается, коль в посте упоминается фабрика > объектов, то создание дополнительных виртуальных методов не увеличит размер экземпляра. А накладные расходы на лишний пустой > косвенный вызов просто несущественны перед ужасом, описанном в посте.
Дело вовсе не в виртуальных вызовах, они там как были так и остались. Для своей работы врапперам нужны дополнительные данные, и эти данные кушают «лишнюю» память. В некоторых объектов оптимизация доходит до того, что double, который хранит проценты ужимается до 4х байт…
> На самом деле это был не совсем планшет, это гибридное устройство, т.к. была возможность
> пристегивать к нему клавиатуру и использовать как обычный ноутбук. Эту идею, ИМХО, неплохо было бы
> применить и к современным устройствам подобного типа.
Мне кажется в современных устройствах клавиатуры неплохо «пристегиваются» через USB или bluetooth
Будучи запущенным эта программка появляется при нажатии волшебной комбинации Ctrl+Shift+Ё и позволяет убить/приостановить/поменять приоритет любому процессу включая системные.
Сам Process Killer имеет приоритет Time Critical, поэтому работает практически во всех ситуациях.
Кроме того, можно понизить приоритеты CPU и IO по умолчанию для некоторых приложений.
Следующий .reg файл установит на минимум приоритеты для cl.exe (это c++ компилятор, цель — избавиться от диких тормозов пока оно компилирует; на скорость собственно компиляции это практически не влияет (если не запускать параллельно с ней чего-нибудь тяжелого), а вот отзывчивость системы при, скажем, серфинге интернета увеличивается в разы).
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\cl.exe\PerfOptions]
"CpuPriorityClass"=dword:00000001
"IoPriority"=dword:00000001
Я думаю, смысл понятен — замыкание — это лямбда ф-я, которая захватила что-то из контекста, если ничего не захвачено, то это просто лямбда ф-я, а не замыкание, я просто старался это показать как можно более наглядно :)
з.ы.
Замыкания же — это подмножество first-class функций, которые используют переменные из окружающего контекста без передачи их в качестве параметров.
1. То, что Вы называете замыканиями — это лямбда функции, а замыкание это нечто другое:
boost::function< int ( int ) > make_adding_func( int t )
{
return [=]( int a ){ return a + t; };
}
...
auto f = make_adding_func( 5 );
assert( f( 10 ) == 15 );
auto g = make_adding_func( 7 );
assert( g( 10 ) == 17 );
В этом коде f и g — это замыкания вокруг 5 и 7 соответственно.
2. Я копался во внутреннем устройстве лямбда функций, они не могут быть сконвертированы в указатель принципиально, т.к. на самом деле являются функторами (классами с оператором скобочки), у них есть конструктор, деструктор и т.п. (попробуйте сами поотлаживать с включенным ассемблерным листингом). [вышесказанное справедливо для MSVC2010]
Правда, есть пару замечаний
1. То, что Вы называете замыканиями — это лямбда функции, а замыкание это нечто другое:
boost::function< int ( int ) > make_adding_func( int t )
{
return [=]( int a ){ return a + t; };
}
...
auto f = make_adding_func( 5 );
assert( f( 10 ) == 15 );
Вот эта функция возвращает лямбда функцию, которая замыкается вокруг t.
Это я читал, но из этой статьи я сделал вывод, что конфликт возникает в том случае, когда редактировалась одна и та же строка файла одновременно. В svn точно так же.
Другими словами, хотелось бы увидеть пример, где работа merge действительно отличается.
Посмотрите, например, реализацию boost.
«Сложно» взято в кавычки потому, что сложно только в том случае, если Вы его никогда не писали. Там думать надо немного по-другому :)
По поводу кодогенерации, то в проекте она есть, принцип следующий: сначала генерируем тип шаблонами, затем вызываем специальную программку, которая выводит в .cpp файлы typeid( TGeneratedType ).name() в нужных местах, это одним махом раскрывает все метавызовы под отладкой жить становится значительно проще :)
Возможно, когда-нибудь я перейду таки на полноценную кодогенерацию в таких местах…
Если вы под субклассами понимаете агрегацию, то в данном случае это не работает, т.к. затраты на указатели становятся слишком большими (объектов, просто, много). В итоге получается большое дерево наследования, которым надо как-то управлять, чтобы не сойти с ума при попытке добавить туда еще что-то. :) При этом сильно экономиться память, т.к. одинаковых по конечному типу объектов много, и вся динамическая информация храниться в таблицах виртуальных функций (которые по одной штуке на тип).
Большие проекты симулируются несколько дней на нескольких компьютерах (уровня i7). Полученные данные хранятся внутри атомов (тех самых объектов) здоровенного гиперкуба. Количество атомов при некоторых условиях достигает 100-200 миллионов.
ООП хорошо работает с целыми объектами. Шаблоны позволяют конструировать целые объекты из множества ПРОСТЫХ «деталек». Отдельно взятые «детальки» (врапперы, стратегии) целым объектом считать нельзя, они лишь реализуют какую-то определенную деталь поведения объекта. Чтобы объекты из этих деталек собирались нормально, а не впадали в «панику» из-за того, что кто-то скрепил детальки не в том порядке, в котором нужно, и используется информация о типах.
С точки зрения фабрики динамика означает лишь одно: на этапе инициализации вычислений мы можем проанализировать, какая функциональность потребуется от того или иного объекта, используя шаблоны мы можем собрать объект из «деталек», который будет нести в себе только эту функциональность, в противном случае все объекты были бы монстрами, способными обработать множество ситуаций, платой за что является либо память либо производительность.
Дело вовсе не в виртуальных вызовах, они там как были так и остались. Для своей работы врапперам нужны дополнительные данные, и эти данные кушают «лишнюю» память. В некоторых объектов оптимизация доходит до того, что double, который хранит проценты ужимается до 4х байт…
> пристегивать к нему клавиатуру и использовать как обычный ноутбук. Эту идею, ИМХО, неплохо было бы
> применить и к современным устройствам подобного типа.
Мне кажется в современных устройствах клавиатуры неплохо «пристегиваются» через USB или bluetooth
Может Вы просто слишком быстро думаете? ;)
(я вообще с .net дела не имею, поэтому слабо представляю, как там работает обфускация)
Неужели обфускация неспособна превратить названия полей в бессмысленные наборы букв?
soft.oszone.net/program/572/Process_Killer/
Будучи запущенным эта программка появляется при нажатии волшебной комбинации Ctrl+Shift+Ё и позволяет убить/приостановить/поменять приоритет любому процессу включая системные.
Сам Process Killer имеет приоритет Time Critical, поэтому работает практически во всех ситуациях.
Кроме того, можно понизить приоритеты CPU и IO по умолчанию для некоторых приложений.
Следующий .reg файл установит на минимум приоритеты для cl.exe (это c++ компилятор, цель — избавиться от диких тормозов пока оно компилирует; на скорость собственно компиляции это практически не влияет (если не запускать параллельно с ней чего-нибудь тяжелого), а вот отзывчивость системы при, скажем, серфинге интернета увеличивается в разы).
Еще можно поставить что-нибудь вроде этого:
з.ы.
Замыкания же — это подмножество first-class функций, которые используют переменные из окружающего контекста без передачи их в качестве параметров.
полностью согласен :)
Красивый код, спасибо.
Правда, есть пару замечаний:
1. То, что Вы называете замыканиями — это лямбда функции, а замыкание это нечто другое:
boost::function< int ( int ) > make_adding_func( int t ) { return [=]( int a ){ return a + t; }; } ... auto f = make_adding_func( 5 ); assert( f( 10 ) == 15 ); auto g = make_adding_func( 7 ); assert( g( 10 ) == 17 );В этом коде f и g — это замыкания вокруг 5 и 7 соответственно.
2. Я копался во внутреннем устройстве лямбда функций, они не могут быть сконвертированы в указатель принципиально, т.к. на самом деле являются функторами (классами с оператором скобочки), у них есть конструктор, деструктор и т.п. (попробуйте сами поотлаживать с включенным ассемблерным листингом). [вышесказанное справедливо для MSVC2010]
Правда, есть пару замечаний
1. То, что Вы называете замыканиями — это лямбда функции, а замыкание это нечто другое:
boost::function< int ( int ) > make_adding_func( int t ) { return [=]( int a ){ return a + t; }; } ... auto f = make_adding_func( 5 ); assert( f( 10 ) == 15 );Вот эта функция возвращает лямбда функцию, которая замыкается вокруг t.
Другими словами, хотелось бы увидеть пример, где работа merge действительно отличается.