ПрограммированиеФорумОбщее

Линус Торвальдс ненавидит С++. А мы с вами? (7 стр)

Страницы: 16 7 8 930 Следующая »
#90
20:59, 28 июня 2010

cNoNim
>> мне не совсем понятно если честно как решение пускай даже на дискрипторах поможет в описываемом тобой случае
Дык элементарно просто - у контекста будет метод clone(), который создаст копию самого контекста и в ней - копии внутренних таблиц текстур/шейдеров, а также вызовет метод wglShareLists(). После чего полученные юзером дексрипторы (айдишники, фактически - смещения внутри таблиц) безо всяких изменений можно будет использовать в обоих контекстах.

В случае double dispatching'а все еще проще, потому что внутренних таблиц у нас нет :) Сразу после wglShareLists() выданные юзеру интерфейсы можно будет биндить в обоих контекстах.

В случае же жесткой привязки текстуры к контексту будет ой-ой-ой.

>> мульти-апи
Забудь про мульти-апи, разговор теперь более простой - про скрытие реализаций двух сильно связанных интерфейсов и возможности их последующего совместного использования.

#91
21:03, 28 июня 2010

crsib
Я не очень жестко вел дискуссию? Извини, если обидел. Просто очень не люблю тайпкасты, вот меня и понесло.

#92
21:08, 28 июня 2010

Z
Земледелец, извини - я, по-моему, чересчур жестко отреагировал на твой первый пост. Меня сегодня понесло что-то :(

#93
21:08, 28 июня 2010

winter
> (Type *)
C-каст. Фи)

winter
> а) дурной тон вообще;
В общем случае, да.

winter
> описанные в этом треде случаи даже не близки к крайним
Описанные в данном треде позволяют безопасный static_cast

winter
> если ты сам семантически проверил его безопасность
Я гарантирую, что он семантически верен. Хочет этого кто или нет, но я четко знаю, какой тип будет реально у интерфеса. Твой код, заметь, тоже не исключает возможность поведения пользователем через ****. Например reinterpret_cast во внешнем коде. Ровно как и код Суслика.

winter
> Следовательно, считать твое решение хорошим или вообще сколь-нибудь приемлемым
> никто не будет.
Еще в обществе считается дурным тоном делать вызов функций, в которых на сам вызов будет затрачено больше времени, чем на выполнение. Дабл-диспатч в данном случае - это как раз такой вариант.)

winter
> занимаем совершенно непримиримые позиции по данному вопросу и твои попытки
> убедить меня в чем-то закончатся ничем
Уговорил. Но все же не тот пример ты привел) Есть примеры, где double-dispatch - отличное и, при грамотной реализации, очень удобное решение. Элджер стайл это плохой подход к дабл диспатчу. Элджеровский код, кстати, в чистом виде не компилируется. А в том, в котором компилируется - пример плохого дизайна системы. Слишком много не нужной информации напрямую доступно пользователю. Кстати наиболее общий и  один из наиболее быстрых и расширяемых способов двойной диспетчеризации от Александреску базирован на рефлекшене)

winter
> В случае же жесткой привязки текстуры к контексту будет ой-ой-ой.
И еще раз. Текстура не привязывается к контексту. Она может на него устанавливаться. Но связанна она именно с девайсом. Если хочешь, то можно считать девайсом фабрику, порождающую контекст и текстуры. Заметь - контекст и девайс семантически разные вещи.

Давай заменим пример. Например на реализацию variant типа. Или на разработку некой примитивной системы коллизий. Потому что дабл-диспатч применим только к объектам, находящимся на одном семантическом уровне. Что не так для системы текстура-девайс-контекст.

@winter
Не, всегда приятно порассуждать на вопросы вселенского мироздания))

#94
21:15, 28 июня 2010

crsib
Элджер - рулез!
Но я согласен, что double dispatching в его случае открывает слишком много информации - собственно, что я и имел в виду, написав про "срам" в конце нулевого поста.

Если ты укажешь мне другой способ делать dd, причем без кастов, без дополнительного сохранения указателей внутри объектов и без рефлекшна - буду рад. ИМХО это невозможно, но буду рад ошибиться.

<правка>
>> Еще в обществе считается дурным тоном делать вызов функций, в которых на сам вызов будет затрачено больше времени, чем на выполнение.
Хмм, ну если так посчитать, затраты на вызов dd-метода - это затраты на вызов виртуального метода... Тело dd-метода - это, по определению, вызов другого виртуального метода... Т.е. на выполнение будет потрачено в среднем ровно столько же времени, что и на вызов.

#95
21:21, 28 июня 2010

Z

> Тоесть будем в дивайсе тайпкастить и трогать кишки текстуръ из дивайса?
> Ето ведь не особо "ООП", разве нет?
Хех, "ООП практически такая же мистификация как и искусственный интеллект".

#96
21:33, 28 июня 2010

winter
> без кастов, без дополнительного сохранения указателей внутри объектов и без
> рефлекшн
Ну, сохранение указателей это лишнее)) А так в, общем случае, действительно никак
Хотя рефлекшн сводится к добавлению одного виртуального метода)
Тут всегда надо балансировать на грани расширяемость-производительность. В любом случае. Либо касты, либо интрузивный подход. И в случае интрузивного подхода в большинстве случаев рефлекшн будет давать значительно больше плюшек, чем отнимать производительности. Возможно тебе это покажется странным, но рефлекшн часто применяется даже в performance critical коде. И не стоит забывать про людей, которые за использование виртуальных функций в этом самом perf critical коде готовы отрывать голову.

winter
> Т.е. на выполнение будет потрачено в среднем ровно столько же времени, что и на
> вызов.
Не совсем точно выразился. Правильное слово - соизмеримо.

#97
21:40, 28 июня 2010

crsib
>> Возможно тебе это покажется странным, но рефлекшн часто применяется даже в performance critical коде
За всю свою практику ни разу не встречал рефлекшна в performance critical коде, даже в жаве, где рефлекшн уже встроенный. Самое ходовое использование - для skeleton'ов и stub'ов удаленных объектов, т.е. не внутри, а снаружи бизнес-логики (на стыке объектов с middleware).
Можешь привести примеры использования рефлекшна в performance critical коде?

#98
21:41, 28 июня 2010

What is "интрузивный подход"?

#99
21:46, 28 июня 2010

есть еще такой метод, не знаю как называется (паралельный интерфейс?)

// interface.h:

struct ITexture {
   virtual void func1() = 0;
   virtual void func2() = 0;
   ...
};

struct IDevice {
   virtual ITexture* CreateTex() = 0;
   virtual void Bind( ITexture* ) = 0;
   ...
};

IDevice* CreateDevice();

// impl_dx.h:

struct Texture {   // не наследуемся
   virtual void func1()  {...}
   virtual void func2()  {...}
   ...
   members;
};

struct Device {   // не наследуемся
   virtual Texture* CreateTex()     {  return new Texture;  }
   virtual void Bind( Texture* p )  {  p->member;... }
   ...
   members;
};

IDevice* CreateDevice()
{
   return (IDevice*)new Device;   // единственный каст тут
}

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

есть подозрение что в dx сделано именно так.

#100
22:14, 28 июня 2010

winter
> Можешь привести примеры использования рефлекшна в performance critical коде?
Рефлекшн например используется в коде симуляций в CERN. Во всяком случае они так говорят. Здесь про рефлекшн писал Сергей Макеев.
Я не совсем понимаю удивления. То, что нужно от рефлекшена в P-C коде - это безопасность приведения типов. И не более. Для ее обеспечения достаточно одного виртуального вызова и одного сравнения. Причем фактически zero-cost сравнения на современных процессорах. А лишний виртуальный вызов и так есть в дабл-диспатче. То есть мы в любом случае разруливаем проблему с типами за 2 виртуальных вызова. Но при этом имеет в подарок кучу плюшек, правда уже не для P-C кода

Adler
> интрузивный подход
Подход, требующий адаптации интерфейса под детали реализацию. То есть добавления методов/полей не имеющих отношения к прямой функциональности. Хотя это очень грубое определение.

uce
> (IDevice*)
Очень плохой каст. По факту reinterpret_cast. Вот так точно нельзя делать. К тому же кто его этот компилятор знает, что ему в голову взбредет. static_cast по крайней мере гарантирует, что vtable окажется в нужном месте (при условии что мы кастуем в правильный тип)

#101
22:15, 28 июня 2010

uce
> uce
это нечем не отличаться от наследование от ITexture  и IDevice  тока является намного опасней.

можно так замутить, типы будут проверяться на момент компиляции

template< int _ID_ > class Device;
template< int _ID_ > class Texture;

template< int _ID_ >
  class Device
{
  enum {ID = _ID_ };
  Texture<_ID_>& create();
  void bind(Texture<_ID_> &txtr);
};
template< int _ID_ >
  class Texture
{
  enum {ID = _ID_ };
};

template< int _ID_ >  void bind(Device<_ID_> &dvc, Texture<_ID_> &txtr);


для программ можно замутить что то типа то кого.

template< typename STRUCT > 
  class CProgram: protected gl::program::CProgram , public STRUCT
{
  public:
    void init(gl::program::SUniform1i STRUCT::*offset);
    void set(gl::program::SUniform1i STRUCT::*offset, uint32 i);
    ...
private:
};

--------------------------------------------------------
struct prgS {
  gl::program::SUniform1i sText;
  gl::program::SUniform4f vEye;
};
CProgram< prgS > prg;

.. f(...)
{
  prg.init(&prgS::sText);
  prg.set(&prgS::sText,34);
}

если взять за провела для каждой программы свою struct prgS  то проверка будет проходить на момент компиляции.

#102
22:21, 28 июня 2010

Нет динамического полиморфиза) Не катит. При его отсутствии нет проблем с сильной связанностью интерфейсов, потому что "производные" типы для компилятора будут отличаться. Но есть очень много проблем. Например интерфейс не отделим от реализации.

Впрочем, производительность будет на высоте)

#103
22:29, 28 июня 2010

winter
> То, что Торвальдс - абсолютный моральный урод,
вот это правильно (если он ругает С++, а он, насколько я понял из контекста ОПа, его ругает).

> совершенно неудобоваримые, слабосильные генерики, невозможность
> объявления константных методов/ссылок и отсутствие перегрузки операторов, на
> мой взгляд, перевешивают встроенную сборку мусора.
Я бы сказал, не "перевешивают", а "дополняют" (ибо сборка мусора, что бы там ни говорили, суть генетическое архитектурное уродство).

> Торвальдс спорит с этим утверждением, указывая на простой факт: внутренняя
> кухня операционной системы лучше всего описывается вовсе не объектами, а
> системами объектов и взаимодействиями между ними. Следовательно, ООП с его
> "малой сцепленностью" сразу идет как бы далеко и надолго, и мы вынуждены
> вернуться к старой процедурной парадигме: данные и функции для работы с ними.
> Несколько раз (сразу нужно сказать, что нечасто) я встречался с чем-то подобным
> - например, когда проектировал свой видео-движок.
Это как бы верно и не только для операционной системы. Но, если на основе этих соображений торвальдс критикует С++, он глуп. С++ хорош как раз тем, что, в отличие от жабы и сотоварищей, это не язык ООП. Что бы там ни думали по этому поводу страуструпы и саттеры. С++ - это в первую очередь язык удобного и логичного синтаксического сахера над "старой процедурной парадигме: данные и функции для работы с ними". Можно на нём писать ООП, можно алгебраически-ориентированный код, а можно что-нибудь ещё. А можно и всё это даже комбинировать в пределах одного куска кода. Чем С++ и силён, в отличие от.

#104
22:34, 28 июня 2010

>Очень плохой каст. По факту reinterpret_cast. Вот так точно нельзя делать.
ничего там страшного не случится, зато это единственный каст на всю систему
>К тому же кто его этот компилятор знает, что ему в голову взбредет.
я то знаю)

Страницы: 16 7 8 930 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.