Здравствуйте, c-smile, Вы писали:
CS>Правда хочется иногда прыстально так глянуть в лицо комитету и спросить "где например метафункция is_pod_type() или там type_info времени компиляции, господа писатели? Доколе в эмпиреях парить будем?" но это так, опционально, хотя тортик для встречи я уже припас.
Я уже упоминал как-то об этом, здесь все дело в традициях. Дело в том, что товарищ Керниган Томпсонович Ричи сильно схалтурил в свое время, дав народу на редкость убогий препроцессор — ну не доработали они. Да и вообще. надо было делать не пре-процессор, а просто хороший макро-процессор, как в MACRO-11.
Осмелюсь высказать крамольную мысль, что UNIX и язык C были чисто гаражно-наколенной разработкой, очень хакерской, без какой-либо серьезной теоретической проработки.
Товарищ Страу Струпович был связан по рукам и ногам, задавшись целью полной обратной совместимости и тоже напроч забыв в свое время о таком понятии, как макро-программирование. Потом, во времена разработки шаблонов ему стало стыдно и он решил выкрутиться из ситуации, введя более круто звучащий термин "мета-программирование".
И сегодняшний комитет в лучшем виде пожинает эти плоды — язык снискал всеобщую симпатию и волей-неволей приходится придерживаться замшелых традиций, дабы не обидеть производитей компиляторов.
Я вполне понимаю комитет — непросто все это. Вот, например, есть такой замечательный язык Ада, разработчики которого решили пресечь на корню разные толкования их "талмуда" и заставили соблюдать строгую сертификацию. Ну и где этот язык теперь? Народ очень сопротивляется, когда некое министерство обороны пытается навязывать свою волю. Народ любит свободу...
The Differences Between Kernighan, Ritchie, and Thompson
I read,
Looks like folks are now beginning to credit the development of UNIX to Kernighan and Ritchie, but I thought the principal investigators were *Thompson* and Ritchie. Did something change?
The differences between Kernighan Ritchie Thompson are real but very subtle. We all look alike (middle aged with scruffy graying beards). Note these distinctions:
Kernighan is slimmest, Ritchie middlest, Thompson heaviest in body build
Ritchie got contacts a couple of years ago and so is the only current non-glasses wearer
Thompson wouldn't touch netnews with a pole, Kernighan secretly gets misc.invest and misc.taxes mailed to him, Ritchie reads it more than is good for him and occasionally contributes
Ritchie is the only one who has met five people who have appeared on David Letterman (Penn, Teller, Rob Pike, Mayor Koch, and the guy who raised the biggest hog in Ohio)
Kernighan has written ten times as much readable prose as has Ritchie, Ritchie ten times as much as Thompson. It's tempting to say that the reverse proportions hold for code, but in fact Kernighan and Ritchie are more nearly tied and Thompson wipes us both out.
Dennis
Здравствуйте, McSeem2, Вы писали:
MS>Верю. Я просто придираюсь к приставке "мета-". Метапрограммирование по большому счету означает "программирование программирования" и является оксимороном. На мой взгляд люди, оперирующие этим термином слишком много на себя берут, в то время как в реальности все гораздо проще....
Есть сообщество людей которые в голове держат C++ template компилятор (у них там есть место свободное под него) и у которых есть время заниматься этим странным делом — программированием на фрагменте мета языка совершенно для того (программирования) не приспособленном.
На самом деле польза от этого есть — в борьбе со змием вырабатываются концепции и требования к будущей стройной концепции.
Хочется верить что творцы (в хорошом смысле) boost со товарищи не растратили себя до конца в героическом преодолении трудностей.
Хотелось бы чтобы они отдавали себе отчет что это не более как эксперимент к реальной
жизни пока не относящийся. И в книжках писали соответсвующим образом не дуря голову окружающим. Ни один нормальный практик не станет использовать мета конструкции поведение которых он не в состоянии предсказать за 10 минут чтения оных.
А так как мы с тобой "вышли из народа" — сиречь программисты-практики то:
"Многие вещи нам непонятны не потому, что наши понятия слабы; но потому, что сии вещи не входят в круг наших понятий "
Т.е. для тех задач которые мы пишем достаточно использования templates по их прямому назначению и в классической позе.
А мета генераторы в стиле HTML-generated-by-PHP мы и так себе можем сваять если нам надо (PHP с Апачем хотя бы варнинги на человеческом языке пишут). Не биг дил.
Правда хочется иногда прыстально так глянуть в лицо комитету и спросить "где например метафункция is_pod_type() или там type_info времени компиляции, господа писатели? Доколе в эмпиреях парить будем?" но это так, опционально, хотя тортик для встречи я уже припас.
Здравствуйте, AndrewVK, Вы писали:
AVK>Никаких ограничений на выполнение основной задачи дженериков — дженерик программирования, это не накладывает. Что же касается возможностей метапрограммирования — плюсовые шаблоны это один из худших вариантов, который можно придумать.
Подобные заявления попадают под категорию (цитируя классика) "космического масштаба и космической же глупости о том, как все поделить".
Шаблоны в C++ — ужасны. Но что-то пока не видать ни одного другого языка программирования, в котором было бы что-то подобное, с такой же свободой выражения мыслей и такой же эффективностью кода. С++ — язык свободы, за что он и снискал всеобщую любовь и всеобщую ненависть.
На самом деле, все выпады дот-нетчиков в сторону C++ сводятся к одной простой фразе:
Если вы все такие умные, чего же вы строем не ходите?
Без обид!
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Павел Кузнецов, Вы писали:
>>> C++ные шаблоны нельзя скомпилировать принципиально. Для компиляции нужно нечто вроде нетовских дженериков.
ПК>>Это не так. Скомпилировать шаблоны до уровня распространения в виде статических библиотек вполне возможно. Естественно, это не будут "обыкновенные" .obj-файлы, но и сборки .Net ими тоже не являются.
AVK>Естественно в такой постановке возможно. Можно например исходники запаковать . AVK>На самом деле вопрос в том что такое компиляция. Плюсовые шаблоны нельзя обработать дальше AST и при экспорте максимум что можно сделать это сохранить его в бинарном виде. Все равно компилятору (именно компилятору, а не линкеру) потом придется с этими шаблонами работать. А вот в дотнете дженерики именно скомпилированы, там нормальный IL-код внутри. Это примерно как если бы в С++ шаблон можно было бы запихать в dll, да так чтобы при смене этой dll поведение программы изменилось без перекомпиляции использующего кода.
Это достигается за счет очень серьёзных ограничений на возможности дженериков. Для шаблонов это неприемлимо.
AVK>Для плюсов это невозможно, поскольку невозможно до развертывания шаблона определить токен используемых методов (адрес статического метода, номер слота виртуального и т.п.). AVK>Какие от этого бенефиты? Вобщем то вполне очевидные:
AVK>1) Нормальная работа в компонентной среде, возможность создания дженерик-компонентов. AVK>2) Быстрая компиляция. Наличие в проекте дженериков практически не влияет на скорость компиляции. AVK>3) Нормальная работа Intellisence, рефакторинга. Нормальная диагностика ошибок.
AVK>4) Отсутствие дублирования кода в скомпилированных модулях.
Нет никакого "дублирования кода" в шаблонах. Код, сгенерённый из шаблона для существенно разных параметров приципиально разный. Это не один и тот же код, повторенный несколько раз, это просто разный код. Возьми, например, какоё-нибудь алгоритм, типа for_each и примени его к итератору вектора и к итератору списка. Получишь существенно разный результирующий код. В этом и заключается главное свойство шаблонов -- они позволяют программировать абстрактно на очень высоком уровне абстракции, не теряя при этом в производительности.
Да, и кстати, кто-то тут любит повторять, что "память больше не ресурс"?
AVK>5) В условиях managed-языков — меньше нагрузка на JIT.
Это странный бенефит. Эачем пользователю JIT, если он купил и установил один раз приложение? На хрена ему каждый раз при загрузке его докомпилировать? Это полный идиотизм.
Все эти бенефиты не стоят тех ограничений на использование, которые приходится накладывать на дженерики.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Шахтер, Вы писали:
AVK>>>Да? А если мы возьмем обыкновенные контейнеры? Там именно что дублирование — разница только в адресах функций и размерах оперируемых данных.
Ш>>Да? А не освежить ли тебе память и не посмотреть ли на то, как устроен итератор по вектору и по списку?
AVK>возьмем обыкновенные контейнеры
Вектор и список -- самые что ни на есть обыкновеннейшие контейнеры.
AVK>Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование.
Просто не могу вкурить, что ты хочешь сказать. Наверно, я тупой.
AVK>Итераторы как раз и есть метапрограммирование.
Уф. Итераторы никаким боком не относятся к метапрограммированию. Метапрограммирование -- это набор техник, позволяющих провести вычисление над типами и константами во время компиляции.
Итераторы -- это как раз хороший пример обобщённого программирования.
И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может. Если при использовании дженериков получается один и тот же MSIL код, то это означает только одно -- никаким обобщённым программированием там и не пахнет, максимум что там есть -- старый банальный полиморфизм (поданый под новым соусом).
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Проблема только в том, что определить грань между generic программированием и метапрограммированием далеко не всегда легко.
Точно! Может скажу и не в кассу, но слово "метапрограммирование" во мне до сих пор вызывает какой-то ступор, почти как "контрреволюция" — совершенно не понятно, что под ним скрывается. С этой точки зрения термин "generic" — гораздо более удачен. Есть сильное подозрение, что он рассчитан на профанов типа меня, не понимающих слова "метапрограммирование"
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>У меня тоже сложилось похожее ощущение. Насколько я понимаю, generics от "банального полиморфизма" в C# отличаются (только) тем, что позволяют лучше контролировать соответствие типов во время компиляции, плюс позволяют избегать множества приведений типов, в противном случае неизбежных без написания своих переходников к контейнерам и т.п.
Думаю, когда-нибудь ты поймешь, что это очень верный, бескомпромиссный выбор архитекторов дотнета. Выбор архитектурно-чистого решения. Решения которое позволит писать код без компромисов. Конечно написать подсистему компиляции выжывающую максимум проихводительности будет несколько сложнее, но впролне возможно.
Надеюсь не нежно объяснять почему такое решение является правильным?
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>А от плюсов мня все больше и больше ташнит. Когда-то это был мой любимый язык. Он даже стал круче с тех пор как я забил на него. Но писать на нем не тянет. А воспоминания о нем далеко не радужные.
То есть, был любимый язык, а теперь — тошнит? Это бывает. Подозреваю, что виноват не C++, а наикривейшие программы на нем, с которыми тебе приходилось иметь дело. Это такой психологический феномен — сексуальные неудачи юности могут обобщиться и развиться в различные фобиии и девиации. Точно так же, неудачный опыт с неким конкретным кодом на C++ в твоем сознании трансформировался в резкую неприязнь всего языка. Я язык-то здесь и не причем. Но вообще-то, правильно — C++ таит в себе очень мощную психологическую нагрузку — не всякий выдержит. Не для слабаков он.
А вот от чего лично меня тошнит — так это от форм-дизайнера. Более тупой, грязной и тошнотворной работы и представить себе сложно. Я считал, что хуже ручной верстки форм на HTML ничего и представить себе нельзя. Однако есть нечто гораздо хуже — называется дизайнер форм.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
AndrewVK,
> ПК>Ничего подобного. Итераторы программой как данными не оперируют. Более того, ничего принципиально декларативного в них тоже нет: > ПК>
> ПК>std::vector<int> v( 10 );
> ПК>for (std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i)
> ПК> *i = e - i;
> ПК>
> ПК>самая что ни на есть итеративная программа.
> Сам итератор декларативно задает некий алгоритм. Натуральная метапрограмма.
Никакая это не метапрограмма, самая обычная абстракция. Давай выкинем шаблоны, но, скажем, оставим итератор для самописного контейнера VectorInt, повторяющего функциональность std::vector<int>. В этом случае его итератор по-прежнему VectorInt::Iterator является метапрограммой?
А если мы изменим VectorInt и его Iterator, так что они будут реализовывать интерфейсы IIteratableContainerInt и IIteratorInt, итератор VectorInt::Iterator по-прежнему будет метапрограммой?
Далее, можно взять аналогию еще и из другой области. Допустим, функция sort() принимает интерфейс предикат, устанавливающий порядок, какой-нибудь IComparator. Классы, реализующие этот IComparator, будут "задавать некий алгоритм". Это тоже метапрограммирование?
Если да, то половина паттернов GoF будет метапрограммами
В общем, если вернуться к определению метапрограммирования, которое ты процитировал ранее:
Metaprogramming is the writing of programs that write or manipulate other programs (or themselves) as their data or that do part of the work that is otherwise done at runtime during compile time.
то можно заметить, что оно состоит из трех вариантов:
writing of programs that write other programs (or themselves)
writing of programs that manipulate other programs (or themselves) as their data
writing of programs that do part of the work that is otherwise done at runtime during compile time
Во-первых, можно заметить, что ничего о декларативном программировании здесь нет, так что эту часть твоих рассуждений мы проигнорируем. Сразу очевидно, что ни первому, ни второму варианту итераторы не удовлетворяют. Остается третий вариант, о выполнении части run-time работы во время компиляции. Если трактовать эту часть достаточно широко, то сюда подойдет даже разрешение перегрузки, что вообще-то говорит о "качестве" определения Однако не видно, даже при такой широкой трактовке, чтобы сюда каким-нибудь боком подходили итераторы
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, McSeem2, Вы писали:
MS>Подозреваю, что виноват не C++, а наикривейшие программы на нем, с которыми тебе приходилось иметь дело.
Видимо по собственному опыту...
MS> Это такой психологический феномен — сексуальные неудачи юности могут обобщиться и развиться в различные фобиии и девиации.
Это когда коленки болят? Поведай не опытным.
MS> Точно так же, неудачный опыт с неким конкретным кодом на C++ в твоем сознании трансформировался в резкую неприязнь всего языка.
MS> Я язык-то здесь и не причем. Но вообще-то, правильно — C++ таит в себе очень мощную психологическую нагрузку — не всякий выдержит. Не для слабаков он.
Это заявление я так понимаю тоже сделано на базе личного нервного срыва?
MS>А вот от чего лично меня тошнит — так это от форм-дизайнера. Более тупой, грязной и тошнотворной работы и представить себе сложно. Я считал, что хуже ручной верстки форм на HTML ничего и представить себе нельзя. Однако есть нечто гораздо хуже — называется дизайнер форм.
Я конечно рад за то что твоей жизненный опыт расширелся столь интеллектуальной работай. Но так и не понял что ты хотел сказать то? Ты как-нибудь попробуй без подтекста высказаться. А то мой ум еще пока не отточен филигранной тренировкой в формдизайнере и ручном рисовании ХМЛЯ.
ЗЫ
Ты знаешь, мне вот всегда прикалывает когда ты начинашь общаться в стиле "гуру". Типа "ты видел прямой код...". Я конечно рад, что ты успел попрограммировать на фортране разные устройства для выпиливания лобзиком по бумаге, но это еше не дает тебе право на снисходительный тон.
Ты вроде не сильно старше меня. И знаешь явно не больше. И вес пока тут не имешь такой чтобы снисходительно разговаривать. Так что давай ты не будеш тут меня "лечить". А то мы так и будем упражняться в острословии и изощренности уколов.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> ПК> Это ж только пример. При попытке использования generics, например, для написания обобщенных матриц и векторов (в смысле линейной алгебры) ушьешься передавать туда делегаты. Будет самый настоящий copy-paste на стороне клиента.
> Не уешся. На каждый тип нужно ровно один делегат.
На каждую используемую операцию каждого используемого типа — по делегату.
> И передавать его не нужно. Положи ссылку в поле и используй. А если методов много, то заведи дженерик-интерфейс с ними.
Ага. Не работает. Методы такие: +, -, *, / и т.п., т.к. generic алгоритм должен работать и со встроенными типами.
> Реализация такого чуда — это пара пальцев об асфальт. Студия 90% работы слелает... За-то все четко специфицировано и явно.
Предлагаемая тобой автоматизация дублирования кода обобщенным программированием не является.
> ПК>Я все еще жду примера, где generics дают что-нибудь новое по сравнению с обычным классом, если закрыть глаза на приведение типов. > > Что нового можно найти после появления структурного программирования? Если я чего-то не понимаю, то держни... покажи класс. Сделай на шаблонах это новое, но без метапрограммирования, плиз.
Любой пример параметрического полиморфизма. Например:
template<class T>
Vector3<T> operator *( Vector3<T> const& v, T const& s )
{
return Vector3<T>( v1.x * s, v1.y * s, v1.z * s );
}
Будет работать для любых скаляров T, начиная от int, float и заканчивая MyBigInt, MyRational, MyDecimal и т.п. В пример включен подразумеваемый шаблон Vector3<T> и т.п.
> ПК>Да, так яснее. Это же можно сделать и без generics. Они здесь ничего нового по сравнению с обычными классами не дают. > > Не, ну если все типы в object-ах, и постоянный боксинг-анбоксинг, да языком Шарп или Васик, то конечно. Ну, и если память и скорость невозна. Пишут же люди на скриптах? Но тут кто-то расскзаывал о типобезопасности, производительности и т.п. Это не ты был?
С точки зрения типобезопасности (кроме избавления от приведений типов, о чем мы уже упоминали) generics ничего не дают по сравнению с интерфейсами. Производительность у generics тоже не блещет. Впрочем, отсутствие необходимости в boxing/unboxing можно тоже добавить, но это уже речь об оптимизации, а не о возможностях.
> Мы вообще о чем? Ты как-то забавно выкручивашся. Что ты понимашь под обобщенным программированием?
В возможностях: шаблоны позволяют применять к объектам типов, заданных параметрами шаблона, любые операции, которые можно использовать вне шаблонов. Generics не позволяют.
> ПК> Уже написано. <boost/operators.hpp>
> Значит операторы уже мовитон?
Моветон не операторы, а copy-paste.
> ПК> Теперь вернемся к примеру выше, и ответим на вопрос: является ли конструкция ниже примером "статически типизированного программирования": > ПК>
При том, что это был единственный способ, который ты нашел, чтобы избавиться от copy-paste при использовании generics. И к обобщенному программированию этот способ не относится.
> Вот эти конструкции
Этими средствами не получается выйти за рамки интерфейсов. Приходим к тому, с чего начали: кроме избавления от приведений типов generics ничего по сравнению с "обычными" классами не дают. (как верно было замечено, можно добавить избавление от boxing/unboxing, но сути это не меняет)
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Шахтер,
> Вообще, это довольно интересная тема. Если действительно нет особого ускорения, то это значит, что фаза парсинга занимает небольшую долю времени в процессе компиляции, а основную -- как раз фаза кодогенерации, которую нельзя сократить создавая бинарное представление шаблона.
Полагаю, даже если исключить из рассмотрения кодогенерацию, оставив только предшествующие ей фазы, все равно особой выгоды (в плане скорости) от перевода шаблонов в какое-то промежуточное представление не будет: большее время занимает фаза семантического анализа, которую нельзя полностью сделать до инстанцирования шаблонов, т.к. на многие аспекты влияют зависимые имена, которые надо разрешать именно при инстанцировании.
Есть основания полагать, что семантический анализ занимает большее время, чем кодогенерация, т.к. файлы C компилируются заметно быстрее, чем файлы C++ с шаблонами.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Возможно, это субъективно, но в последнем случае у меня доверие к коду намного выше, чем если он был получен ковырнадцатью циклами compile & fix.
Зависит от задачи. Если задача вобщем то ясна, то я могу день писать код без компиляции (раньше использовал изредко, просто чтобы проверить синтаксис, но решарпер позволяет обходится без). А вот если пишешь скажем плагин к студии, то там без массы компиляций и отладки не проживешь, поскольку никакие напряжения мысли не помогут проникнутся особенностями поведения студийного API.
Здравствуйте, VladD2, Вы писали:
VD>Обобщенное — значит применимое для любого типа.
Свойства типов могут зависеть от констант (например, размер), поэтому константы можно рассматривать, как механизм доопределения типов. И вообще, само слово "обобщенный" означает независимый от частностей. В качестве таких честностей вполне могут выступать не только типы, но и константы. Почему нет?
VD>Параметризация же константами — это чистый макросный стиль, или метапрограммирование.
спорно
VD>Если константы просто подставляются, то тоже самое можно добиться простым заданием констант в классе или заменой их на переменные.
Совершенно верно. Точно так же, как статический полиформизм вегда можно заменить динамическим. Ситуация абсолютно идентична.
VD>Если же константы начинают влиять на алгоритм (менять код), то это четкий признак применения шаблонов для метапрограммирования.
Меня не волнует, меняется ли ассемблерный код, или нет. Важно то, что алгоритм семантически одинаков.
VD>Еесли классы/методы отличаются только абстрагированностью от конкретных типов, то это обобщенное программирование. Если имеется элементы кодогенерации — это это уже нечто выходящее за рамки обобщенного программирования.
Кодогенерация тут вообще не причем. Нет такой парадигмы программирования, которая называется "кодогенерация". Это всего лишь, низкоуровневый технический приём.
VD>Несмоненно с помощью метапрограммирования можно эмулировать практически любые расширения ЯП, но это уже отдельный вопрос имеющий опосредованное отношение.
Абсолютно согласен.
Здравствуйте, Шахтер, Вы писали:
Ш>Это достигается за счет очень серьёзных ограничений на возможности дженериков. Для шаблонов это неприемлимо.
Никаких ограничений на выполнение основной задачи дженериков — дженерик программирования, это не накладывает. Что же касается возможностей метапрограммирования — плюсовые шаблоны это один из худших вариантов, который можно придумать.
Ш>Нет никакого "дублирования кода" в шаблонах. Код, сгенерённый из шаблона для существенно разных параметров приципиально разный.
Да? А если мы возьмем обыкновенные контейнеры? Там именно что дублирование — разница только в адресах функций и размерах оперируемых данных.
Ш>Да, и кстати, кто-то тут любит повторять, что "память больше не ресурс"?
А при чем тут память? Речь о размерах файлов и скорости работы линкера.
AVK>>5) В условиях managed-языков — меньше нагрузка на JIT.
Ш>Это странный бенефит.
Чем?
Ш> Эачем пользователю JIT, если он купил и установил один раз приложение?
JIT нужен для работы managed-языков. Некоторые вещи — вроде CAS, без управляемого кода практически нереализуемы.
Ш>Все эти бенефиты не стоят тех ограничений на использование, которые приходится накладывать на дженерики.
Здравствуйте, Шахтер, Вы писали:
AVK>>возьмем обыкновенные контейнеры
Ш>Вектор и список -- самые что ни на есть обыкновеннейшие контейнеры.
Но не итератор. Это вобще не контейнер, а средство работы с ним.
AVK>>Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование.
Ш>Просто не могу вкурить, что ты хочешь сказать. Наверно, я тупой.
Я хочу сказать что метапрограммирование реализуется не только шаблонами. Более того — реализация метапрограммирования шаблонами на редкость неудачное. Отсюда невозможность использовать дженерики для метапрограммирования не есть их недостаток, поскольку они не предназначены для метапрограммирования.
AVK>>Итераторы как раз и есть метапрограммирование.
Ш>Уф. Итераторы никаким боком не относятся к метапрограммированию. Метапрограммирование -- это набор техник, позволяющих провести вычисление над типами и константами во время компиляции. Ш>Итераторы -- это как раз хороший пример обобщённого программирования.
Metaprogramming is the writing of programs that write or manipulate other programs (or themselves) as their data or that do part of the work that is otherwise done at runtime during compile time. This allows programmers to produce a larger amount of code and get more done in the same amount of time as they would take to write all the code manually.
Метапрограммирование это создание программ, создающих программы. Итератор как раз такая программа и есть — декларативное описание на этапе компиляции разворачивается в итеративный код.
Ш>И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может. Если при использовании дженериков получается один и тот же MSIL код, то это означает только одно -- никаким обобщённым программированием там и не пахнет, максимум что там есть -- старый банальный полиморфизм (поданый под новым соусом).
In computer science, generics is a technique that allows one value to take different datatypes (so-called polymorphism) as long as certain contracts such as subtypes and signature are kept. The programming style emphasizing use of this technique is called generic programming.
Дотнетовские дженерики на 100% этому определению соответствуют.
AndrewVK,
> ПК> Никакая это не метапрограмма, самая обычная абстракция. Давай выкинем шаблоны, но, скажем, оставим итератор для самописного контейнера VectorInt, повторяющего функциональность std::vector<int>. В этом случае его итератор по-прежнему VectorInt::Iterator является метапрограммой?
> В этом случае все без особых проблем реализуется на шарпе.
Ну и что? От этого действия, выполняемые итератором, равно как и вид результирующей программы ни на йоту не изменятся. Или все, что реализуемо на C++, но не реализуемо на C# является метапрограммированием?
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
_FRED_,
> Начал замечать за собой такую неприятную ( ) особенность — вместо того чтоб десятый раз пробежаться глазами по строкам, руки тянутся нажать Build и сразу получить все (ну конечно же не все, но...) ответы.
По-моему, ключевой момент в выделенном: контроль со стороны компилятора, автоматизированные тесты и т.п. это только часть средств для написания корректных программ. Основным и самым действенным остается концентрация программиста на процессе написания программы, и постоянная верификация разрабатываемой программы на соответствие придуманной "модельке".
Это не к тому, что я, среди прочих, не страдаю такими же "закидонами": расслабиться, и скомпилить файлик вместо того, чтобы убедиться, что все изменения сделаны правильно. Просто сколько уже раз замечал: стоит позволить себе такое настроение, и почти наверняка что-нибудь существенное упустишь; если же работаешь in flow, с концентрацией на том, что делаешь, то зачастую оказывается, что набиваешь куски вполне приличного размера без единой ошибки компиляции.
Возможно, это субъективно, но в последнем случае у меня доверие к коду намного выше, чем если он был получен ковырнадцатью циклами compile & fix.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, prVovik, Вы писали:
AVK>>Зависит от задачи. Если задача вобщем то ясна, то я могу день писать код без компиляции V>ИМХО, это нехорошо, потому что трудно тогда баги искать.
Какие баги? У меня никаких багов нет, все работает сразу
Здравствуйте, Павел Кузнецов, Вы писали:
>> Щас снова скажу крамолу (вах, боюс-боюс). >> Шаблоны по своей сути — это макросы, какими бы умными "метапрограммированиями" их ни обзывали.
ПК>(Ну и гаразд же ты терминами крутить) собственно, в этом их сила. Как и макросы, шаблоны были призваны заменить собой copy-paste. В отличие от generics, они с этой задачей вполне в состоянии справиться.
Честно признаюсь, я в свое время не мог въехать шаблоны, пока не представил их именно в виде макросов по своей сущности. Тогда все сразу встало на свои места. Для меня основная сила шаблонов — в возможности параметризовать алгоритмы не только интерфейсами, но и базовыми типами и целочисленными константами. Именно это позволяет заменить copy-paste.
Производительность при динамической параметризации (переменными) сразу падает в несколько раз — на любом языке, хоть на ассемблере. Тут уж ничего не поделаешь. А в C#-генериках параметризовать константами нельзя. Единственный выход для сохранения производительности — copy/paste. В минимальном варианте получаем:
2 варианта ValueT — uint8, uint16,
4 варианта Order
3 варианта BaseShift для случая uint16 (12, 14, 16)
Итого 2*4 + 2*4*3 = 32 варианта одного и того же кода в виде банального Copy/Paste.
На голом Си это можно хотя-бы дефайнами сделать (тяжело, некрасиво, но можно). Ни на Java, ни на C#, ни на Фортнане задача не решается в принципе.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, VladD2, Вы писали:
VD>Дык, не ты ли говорил, что если что мы по бырому генератор кода сварганим?
Наверное не я. Напомни-ка.
Я помню то, что я говорил о необходимости иметь встроенный в язык макропроцессор, а не привешенный сверху. Но это уже — совсем другой коленкор.
VD>Сдается мне, что все несколько проще. Это ты своих тараканов размножаешь.
Я не размножаю — они сами размножаются. И главное средство их размножения — это тот самый copy-paste. А я их стараюсь давить — душили-душили, душили-душили...
MS>>На голом Си это можно хотя-бы дефайнами сделать (тяжело, некрасиво, но можно). Ни на Java, ни на C#, ни на Фортнане задача не решается в принципе.
VD>О как. А значит препроцессор у нас религия для Явы или Шарпа запрещает использовать?
Это не религия не позволяет — это практика не позволяет. Вот представь, что я отдаю исходник на C# или Java заказчику весь в дефайнах и ифдефах, и говорю — а компилируйте через cpp.exe и всех делов. В какое место я буду послан?
Короче говоря, надо пользоваться естественными средствами языка. Сишный препроцессор для Си — естественное явление — просто берешь и компилируешь. Тот же самый препроцессор для C# — нонсенс.
Представь, вот просто представь — кто-то решил внести свой вклад в R# и пишет код, который надо обрабатывать Сишным препроцессором. В какое место ты сам его пошлёшь? И будешь прав, что характерно.
VD>А по уму твоя проблема решается кодогенератором. Качаешь R# или КодСмит и через пять минут решение твоей неразрешимой проблемы. Причем чистое, красивое, и легко отлаживаемое.
О! Насчет "чистое и красивое" — это станет возможным только тогда, когда этот самый R# будет встроен в язык и стандартную поставку. Когда это случится? Насчет "легко отлаживаемое" — не верю вообще.
Заметь, что в фигурных скобках может быть весьма нетривиальный код.
Ну, и как это дело трассировать в отладчике (вне зависимости от языка)? Как это решено в кодогенераторе R#?
Здесь только два варианта — либо трассировать не исходный текст, а результат работы кодогенератора (представь, что Сишный отладчик выдает не исходник, а некую абракадабру после обработки препроцессором), либо же не трассировать вообще — как в случае Сишных макросов. Третий вариант — отладчик должен умно разворачивать данные конструкции — типа как при трассировке ассемблерного кода в студии. А это означает, что отладчик должен знать, что есть такое слово, как R#. Так когда это все будет? Мы ждем с нетерпением...
В общем, благодаря этой дискуссии я наконец-то понял, что шаблоны отличаются от макросов тем, что код шаблонов можно трассировать, а код макросов — нельзя. Шаблоны — страшная сила!
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Павел Кузнецов, Вы писали:
>> Опять же интерейс тебе поможет. Кто скзал, что его нужно реализовывать в типе?
ПК>Я сказал.
О. Это серьезный аргумент.
ПК> Эти типы должны быть удобны в использовании и без шаблонов.
Не имеет ни малейшего отношения к делу.
ПК> Плюс это все хозяйство должно работать со встроенными типами и с типами из сторонних библиотек.
Работает.
>> Сделай хэлпер. Ты же в С++ передаешь через параметр разные Аллокаторы и т.п.
ПК>Я о них забочусь только когда они мне нужны (в частности аллокаторы — три или четыре раза за все время).
И я тоже.
ПК> В остальных случаях они под руками не мешаются,
И мне тоже.
ПК> т.к. их явно указывать не нужно.
И мне тоже.
ПК> С generics это не пройдет:
Чушь.
ПК> там все нужно будет делать явно, т.к. даже специализаций нет.
Чушь.
ПК>Методы чего? А если это не оператор *, а вспомогательная функция, которая не может быть членом Vector3<>, т.к. этот класс в библиотеке, а функция — в моем приложении?
Тебе уже сказали как при этом нужно поступать. Хороший пример объекты-компараторы. Погляди как они работаеют.
ПК> В C# не будет работать потому что: нельзя вызвать * для T, нельзя вызвать конструктор для Vector3<T>.
Все будет работать. Просто ты привык работать как привык и принимаешь в штыки любой другой подход.
>> ПК> Впрочем, отсутствие необходимости в boxing/unboxing можно тоже добавить, но это уже речь об оптимизации, а не о возможностях.
>> А о чем еще можно говорить если речь зашла о скорости кода?
ПК>Речь о скорости кода завел ты. Я говорил о возможностях, направленных на облегчение повторного использования кода.
Я только слово сказал, как ты тотчас же попытался использовать его для доказательства своих заблуждений.
ЗЫ
В общем, опять бессмысленный разговор. Тебе очень хочется доказать недоказуемое. Ты находишь какие-то системные проблемы там где их нет. Твое мышление все лежит в рамках подходов навязываемых плюсами. Но есть и дуругие подходы. То что они тебе кажутся недобобными — это всего лишь твоя проблема.
Ну, а что до копипэстов, то не С++-никам про них говорить. В С++ копипэст повсюду. Как минимум разделаная декларация и определение — это уже горы копипэста. С дублированием "x + y" — это даже в сравнение не идет.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Речь шла о шаблонах, об экспорте шаблонов. Причем тут твои слова?
С точки зрения пользователя библиотеки, он оиспользует обычный типобезопасный шаблон со статическим контролем типов. При этом, весь реально работающий код находится в длл, которую можно менять. И чем это ПРИНЦИПИАЛЬНО будет отличаться от генериков?
VladD2,
> ПК> Влад, не смешно. Перечитай предлагавшиеся варианты (выше по ветке). Т.к. generics ограничены возможностями работы через интерфейсы, то можно вынести соответствующие non-generic функции, работающие через ссылки и указатели на интерфейсы, в DLL. Что конкретно не будет работать?
> Ничего не будет работать. Положить полноценный шаблон в длл невозможно. А дженерик раз плюнуть.
Полноценный, естественно, не получится. А неполноценный, типа generics, как уже показали — легко Наличие переходников в заголовках не считается, если ты предлагаешь не считать количество делегатов для передачи операторов в generics: баш на баш, так сказать
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
>> Операторы? Ну, это как сказать. Вот так напрямую может и нельзя.
ПК>Именно о "напрямую" и идет речь.
Я не понял. Тебя интересуют качественные возможности или фишки? Другими словами тебе фишечки нужны или ехать?
То ты тут пафосно заявляешь, что дженерики это замена приведенимя тиов, то начинаешь докапываться до совершенно не принципиальных вещей.
ПК>Теперь, пожалуйста, сделай generic вариант вот этих вот двух функций, чтоб не нужно было делать copy-paste для каждого нового типа. Что, не получается? То-то. Об этом и речь. Вот вариант в виде шаблона: ПК>
ПК>template<class T>
ПК>static T Add(T x, T y) { return x + y; }
ПК>
А у тебя получится? Если тип новый, то и методы у него нужно писать новые. Вот и пиши методы, а уже их вызывай из операторов. В общем, явно попытка поиска ведьм. Признайся что был не прав и не прейдется аргументы из пальца высасывать. Даже смешно ейбогу.
Ну, да ради искуства... напишу тебе универсальную функцию :
static Adder<T> GetAdditionOperator<T>()
{
return (Adder<T>)Delegate.CreateDelegate(
typeof(Adder<T>), typeof(T), "op_Addition");
}
...
TimeSpan timeSpanValue = Accumulate<TimeSpan>(
GetAdditionOperator<TimeSpan>(),
new TimeSpan[]
{
new TimeSpan(10, 0, 0), new TimeSpan(10000),
new TimeSpan(1, 12, 10), new TimeSpan(20000)
});
Console.WriteLine("timeSpanValue is " + timeSpanValue);
На жлабэйские операторы и вовсе доступны в виде методов.
ПК>Ага, с песней. Для каждого типа.
О, блин, проблема! Ты еще не забыл, что это можно просто по месту делать? Анонимные методы еще ведь никто не отменял:
Xxx(delegate(int i) { return new Yyy(i) });
Да и это ты уж совсем из пальца проблемы высасывашь. На практике такие изыки встречаются крайне редко. А фабрики классов обычно делаются на базе активатора, так как в отличии от плюсов все компоненты и любой класс можно создать динамически. С точки зрения фабрики классов намного выгоднее прописать все что нужно в файле настроек и создавать классы по этим описаниям. Например, плагины делаются на раз. Даже КОМ отдыхает.
ПК>Нет, ты сделал второй вариант. Чаще используется первый. Первый ты сделать на C# не сможешь из-за ограничений generics.
Опять высасываем проблему из пальца. Во-первых, смогу. Примерную реализацию я уже показал. А во-вторых, никому не помешает если будет передаваться метод. Функционально код одинаков и даже более абстрактен.
Вообще забавно само желание выискать проблему чтобы обяснить себе почему я не люлю ХХХ. Причем как всегда закапыванием в какие-то далекие от основного вопроса пытаемся уйти от ответа на главный вопрос. Ты еще не забыл, что я тут в основном против твоего заялления о бесполезности дженериков спорю
?
>> В общем, то что ты считашь недоработками или недостаткаи есть резултат отличной работы дизайнеров языка кторым удалось впихнуть в рамки простого языка концепцию обобщенного прграммирования.
ПК>"Пока наши корабли бороздят просторы космоса". Может, оно и "результат отличной работы дизайнеров", но вот простую проблему избавления от copy-paste так и не решает...
Я где-то сдублировал код? Или выдавать желаемое за действительное начинает входить в привычку? Как в прочем и желание найти проблему даже там где ее нет. В примере дублируются только строчки "x + y". И понятно почему. Дженерики не макросы. Они не могут работать текстуально. Операция обязана быть абстрактной. Для абстрагирования есть немало методов.
Не... я был бы только за если бы появились констрэйны типа "+" или "-". Но и без них особых проблем нет. Концепция полна и не противоричива. При чем подталкивает к большему абстрагированию и продумыванию интерфейса. Учитывая на то что язык и среда вообще подталкивают к ООП проблем не возникает. Типы обычно реализуют нужные интерфейсы которые спокойно можно задействовать в обощенном коде.
В общем, опять притягивания за уши. Только что были глобальные заявления про ущербность. Теперь вот откровенй ... про копипэст. Далее, думаю, аргументы будут еще более мелочными и не относящимися к делу.
Ну, а по факту. По факут примера демонстрирующего невозможность реализации чего-то обобщенного нет. Есть только мелочные придирки в основном сводящиеся к тому, что все не так как в С++.
Вот к С++ претензий хоть отбавляй. Попробуй ради хохмы передать ссылку на метод по сети. Получишь гору фрэймворков вроде КОМ или КОРБА и море геморроя.
и бульше не повторять эти заблуждения. Или все же предоставить пример обобщенной задачи, причем без ужимок и высасываний из пальца, который будет нельзя реализовать сдредствами дженериков дотнета. Ну, и закрыть на этом тему.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
AndrewVK,
> исходная мысль была о том, что большинство отличий в возможностях шаблонов имеют практическое значение при метапрограммировании, а не при дженерик-программировании.
Эта мысль не совсем верна. В том смысле, да некоторая часть отличий относится к метапрограммированию, но итераторы к этому никаким боком, пожалуй, как и очень многое из "большинства" отличий шаблонов С++ от C# generics.
> Сам по себе итератор конечно не метапрограмма, но такой же итератор реализуется и на шарпе. Метачастью является функциональный стиль использования итератора — не выполняющий реальной работы, зато улучшающий синтаксис применения.
Да, согласен, данный стиль Шарпом не поддерживается. Но это просто стиль, не метапрограмма. Если бы речь шла об итерации по списку типов во время компиляции, я бы, пожалуй, с тобой согласился.
Об улучшении же синтаксиса применения... Если пойти по этой дорожке достаточно далеко, то мы дойдем до того, что все языки программирования высокого уровня по большому счету являются не более чем syntactic sugar над ассемблером.
И, хотя по большому счету мне все равно, назовешь ли ты такой стиль программирования "улучшением синтаксиса применения", т.к. мне и другим, кто его предпочитает, это помогает быстрее и с большим удовольствием писать более понятные (*) и более легко сопровождаемые (**) программы, все же замечу, что грань между "улучшением синтаксиса" и "выполнением работы" на первый взгляд подчас бывает очень тонкой.
Например, for each в C# — это улучшение синтаксиса или не только? А перегрузка функций? А неявный боксинг? А операторы + — и т.п. вместо функций Add, Substract и т.п.? А properties? А enums? А цикл for (ведь достаточно while)? А оператор switch (ведь достаточно (if ... else if ...)? Если зайти достаточно далеко, то C# generics почти целиком можно списать на улучшение синтаксиса, т.к. значительная их часть сводится к автоматизации приведения типов.
Имхо все это неверно, т.к. все эти вещи, равно как и многие отличия шаблонов C++ от C# generics, позволяют использовать какие-то новые идиомы, и, соответственно, просто к "улучшению синтаксиса применения" не сводятся. По-моему, грань, отделяющая "улучшение синтаксиса" от "выполнения работы" как раз и лежит там, где добавление новых выразительных средств приводит к качественному изменению языка, давая пространство для новых идиом и стилей программирования.
(*) Возможно, не для всех.
(**) Наверняка, не всеми.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VladD2,
> ПК>Да, естественно. Опосредованно шаблоны можно тоже из DLL экспортировать. > > Да ну? А можно пример посмотреть?
На уровне возможностей generics? Пишешь обычный класс + шаблон-обвязку, приводящую аргументы и результаты функций. Класс экспортируется, шаблон включается обычным #include. Все, справился.
> ПК>Пока так и не было продемонстрировано, что позволяют сделать generics, чего нельзя сделать обычным классом, если не принимать во внимание необходимость приведений типов во втором случае.
> Дык написать обобщенный алгоритм или контейнер.
В чем, кроме отсутствия необходимости в приведениях типов, проявляется его обобщенность в случае generics?
> Или ты о том, что и обобщенное программирование и динамический полиморфизм суть проявления полиморфизма и с филосовской точки зрения обладают равными возможностями?
Разными. Параметрический полиморфизм (aka основной инструмент обобщенного программирования) позволяет писать код идентичным образом для разных типов. Generics ограничивают множество конструкций до тех же, что доступны в "обычных", не generic, классах.
> В общем, это несерьезно. Очевидно, что дженерики — это полноценное средство обобщенного программирования. Примеров которые невозможно реализовать ты так и не привел. Признаваться что не прав тоже не хочешь.
Еще раз: конкретно, какие возможности доступны в generics, которые нельзя получить "обычными" классами, если не учитывать приведения типов?
> ПК>Ошибся. Подразумевалось: http://rsdn.ru/Forum/Message.aspx?mid=1016014&only=1
Не хами.
> Я алгоритм реализовал? Он обобщенный? Что еще? Код на Камеа не компилируется?
"Алгоритм" в данном случае сводится x + y. Эту часть ты так в generics и не включил. Точнее, один вариант был, но основанный на "обычных", не generic средствах.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Извиняюсь, что посреди большой философии с такими частностями. Тем не менее...
> Читал, что экспорт шаблонов ещё не сделан.
Сделан в EDG. Сравнительно давно доступен в Comeau.
> Нужен? "Необходим!" ответят, я думаю, многие.
Уверяю, не необходим. Кой-какая польза от него есть, но не принципиальная. Заключается в том, что при наличии экспорта шаблонов можно перекомпилировать не все файлы, зависящие от определения изменившегося шаблона, а только один из них. Имхо, намного полезнее введение модулей, чему, впрочем, экспорт шаблонов, вроде, не мешает.
Хотя, согласен, практического опыта использования экспорта шаблонов пока наработано немного, может оказаться, что какие-то дополнительные бонусы еще не найдены.
Здравствуйте, _FRED_, Вы писали:
_FR>Ага! Значит у всех в С++ шаблонах оно не работает
Нет, нормально не работает. А ты не знал?
_FR> И, к слову, сильно ещё сама среда не готова к дженерикам.
Какая среда?
AVK>>5) В условиях managed-языков — меньше нагрузка на JIT.
_FR>Да, но отсюда же и некоторые их недостатки?
Разумеется. Но надо понимать главное — с синтаксическими шаблонами ни о какой компонентности речи уже не и дет. ИМХО для дотнета это смертельный недостаток, поскольку коллекции, которые нельзя передавать между компонентами резко теряют в своей привлекательности. А для метапрограммирования я думаю нужно что нибудь попривлекательнее шаблонов.
Здравствуйте, Шахтер, Вы писали:
Ш>Думаю, что это было бы полезно, поскольку это помогло бы ускорить процесс инстантинации шаблонов. Насчет дополнительных усилий. При разборе заголовка с шаблонами, компилятор всё равно переводит их в некоторое внутреннее представление, работа с которым, естественно, более эффективна, чем с исходных текстовым. Всё что нужно -- сериализовать это представление в бинарную форму. Это достаточно стандартная задача.
Щас я такое выдам...
На самом деле, форма хранения не важна. Проблема C++ в том, что все стараются придерживаться замшелой парадигмы о раздельной компиляции. Это работает для C и Фортрана, но C++ раздельную компиляцию давным-давно перерос — отсюда все проблемы с экспортом шаблонов. Как верно заметил AndrewVK, можно было бы просто сохранять функции шаблонов в Obj-файлах в исходном виде. Но при этом линкер должен будет вызывать компилятор снова и до-компилировать инстанциируемые шаблоны. А это будет противоречить идее о раздельной компиляции. Раздельная компиляция в современном C++ — это лишь замшелая традиция и ничего более. В конце концов, если посмотреть на командную строку практически любого современного компилятора, то при помощи него можно и компилировать и собирать бинарник. Понятно, что внутри он вызывает ld, но снаружи это выглядит так, как будто я создаю исполняемый бинарник при помощи одной единственной команды — "g++". Если бы не было этого параноидального разделения на компилятор и линкер (другими словами, чтобы линкер тоже мог компилировать), все было бы куда как проще. Больше всего меня поразило, как разрешается конфликт множественных инстансов на сановском C++ workshop. Это в натуре — "шедевр". Там одинаковые инстансы из разных библиотек просто замещают .o файлы с одинаковыми именами. Имена файлов получаются при помощи некой хеш-функции из имени шаблона с параметрами. Что произойдет в случае конфликта (collision) хэш-функции — я так и не знаю.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Шахтер,
>> И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может.
ПК>Извини, немного уточню: может, но не должен
Похоже опять не совсем точно. Может и будет в определённых ситуациях. Например, если шаблон параметризуется типами int * и long * на платформе, на которой физически типы int и long устроены одинаково, то естественно, скорее всего, сгенерится одинаковый код. Тут надо заметить, однако, что современные компиляторы умеют устранять подобное дублирование кода.
Тем не менее, в общем случае, код, скорее всего, будет существенно разным. И в этом большая ценность обобщённого программирования. Оно позволяет лучше "сжимать" код. Т.е. меньшим количеством исходного кода можно получить больше результирующего ассемблерного кода.
AndrewVK,
> Ш>Итераторы -- это как раз хороший пример обобщённого программирования.
>
Metaprogramming is the writing of programs that write or manipulate other programs (or themselves) as their data or that do part of the work that is otherwise done at runtime during compile time. This allows programmers to produce a larger amount of code and get more done in the same amount of time as they would take to write all the code manually.
> Метапрограммирование это создание программ, создающих программы. Итератор как раз такая программа и есть — декларативное описание на этапе компиляции разворачивается в итеративный код.
Ничего подобного. Итераторы программой как данными не оперируют. Более того, ничего принципиально декларативного в них тоже нет:
std::vector<int> v( 10 );
for (std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i)
*i = e - i;
самая что ни на есть итеративная программа.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Никакая это не метапрограмма, самая обычная абстракция. Давай выкинем шаблоны, но, скажем, оставим итератор для самописного контейнера VectorInt, повторяющего функциональность std::vector<int>. В этом случае его итератор по-прежнему VectorInt::Iterator является метапрограммой?
В этом случае все без особых проблем реализуется на шарпе.
Здравствуйте, alexeiz, Вы писали:
A>Купи книжку "C++ template metaprogramming", и всё поймёшь. Я недавно смотрел. Интереснейшая вещь.
Верю. Я просто придираюсь к приставке "мета-". Метапрограммирование по большому счету означает "программирование программирования" и является оксимороном. На мой взгляд люди, оперирующие этим термином слишком много на себя берут, в то время как в реальности все гораздо проще. Вообще, за что я не люблю Алесандреску, Абрахамса и прочих (но уважаю!) — так это за стремление усложнять то, что на самом деле является простым. И еще — за попытки перепрыгнуть через голову C++. Я не против таких попыток и очень их уважаю, но не люблю, когда это все выдается за абсолютную истину. А у них — именно такой агрессивный стиль, типа если ты не можешь понять boost::iterator_adaptor или Loki, значит ты — лох и неуч. Но, думаю, что подобная агрессивность имеет смысл — она стимулирует.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>alexeiz,
>> Купи книжку "C++ template metaprogramming", и всё поймёшь. Я недавно смотрел. <...>
ПК>Ну просто чудеса! Автор еще свою книжку в напечатанном виде от издательства не получил, а народ уже обсуждает
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Похоже, я понял; у тебя разделение между "улучшением синтаксиса" и "выполнением работы" проходит по грани: поддерживатся ли данная "фича" языком или средой исполнения. Мне с такой дихотомией согласиться сложно.
Не соглашайся. Это что то меняет? На самом деле основные мысли были в конце сообщения, а что называть улучшением синтаксиса, а что нет мне вобщем то в контексте обсуждаемого вопроса все равно. Я просто предложил формальный признак.
Здравствуйте, AndrewVK, Вы писали:
AVK>Метапрограмма это код, преобразующий изначально неподдерживаемый С++ функциональный стиль в классический императивный. Т.е. синтаксически корректный, но семантически непонятный стиль при помощи шаблона преобразуется в понятную кодогенератору форму. Проблема в том что многие это воспринимают как нечто уникальное и близкое к идеалу.
Тут ты заблуждаешся. Итераторы С++ ничего общего с метапрограммированием не имеют.
AVK>Более правильным было бы наличие чистых дженериков без побочных эффектов + специализированные средства метапрограммирования, как например в OpenC++, XC#, R# наконец. Вот только чтобы это была стандартная фича языка, а не стороннее средство.
Вот тут согласен. Хотя хоть убей не пойму какого черта нужно мечтать о чем-то, а не взять то что есть?
ПК>> А неявный боксинг?
AVK>А это уже фича рантайма.
Отнюдь. Это фича языка. В МС++, например, автобоксинга нет. Там приходится писать нечто вроде:
Object obj = __box(123);
ПК>> А операторы + — и т.п. вместо функций Add, Substract и т.п.?
AVK>Чисто синтаксическая фича к сожалению.
Ну, вот ты и договорился до того на что тебя Паша подвигал. add и sub — это классика ассемблера. Все же это уже качественное изменение, а не количественное. Так же как if и switch — это качественное изменение по сравнению с cmp & jne.
ПК>> А properties? А enums?
AVK>Поддерживается рантаймом.
Ага. А if и + не поддерживаются?
AVK>Тоже синтаксис. В IL никакого for нет. Офф: знаешь откуда синтаксис for взялся? Практически 1 в 1 скопированно с соответствующего макроса макроассемблеров.
Да без разницы чего нет в IL. IL — это абстрактный ОО-ассемблер. Тут же речь об уровен. Так что любое повышение уровня языка влечет за собой повышение продуктивности программистао.
И совершенно верно то, что метапрогаммирование позволяет повышать этот уровень без изменения базового языка. Веренее метапрограммирование позволяет локально менять базовый язык (под потребности конкретной прикладной области).
И очень жаль, что Паше как всегда удалось увести тебя от сути обсуждения к частностям. Ты совершенно прав в том, что дженерики отличаются от шаблонов (с точки зрения взможностей) только тем, что они не позволяют заниматься метапрограммированием, и позволяют не нарушать компонентную модель (и другие рантаймные тахнологии). И опять же ты прав в том, что метапрограммирование на шалонох убого и является архитектурным артифактом не запланированным создателями языка.
В общем, очень жаль, что ты вовремя не признал свою ошибку в оценке итераторов и пытаешся далее жащищать эту ошибку. Именно используя это ПК с успехом отстаивает в принципяльно неверную позицию.
Ошибка же ПК более глобальна. Для него "С++ — это Аллах, а шаблоны пророк его". И в попытке отстоять это заблуждение он испоьзует любые малейшие ошибки и пробелы в знаниях.
Примитивный примем — подлов на слове и раскручивание ошибок действует очень неплохо. Так что нужно вовремя возвращаться к исходным посылкам признавая мелкие неточности или ошибки.
В данном случае ты не прав, в отношении итераторов. Это просто обобщенный код. Просто код несколько необычный для твоего глаза. Однако это никак не изменяет правоты твоей исходной послыки. И не фига поддаваться на провакации с классификацией структурных операторов и сравнению их с ассемблерными.
AVK>А вобще я не понимаю к чему этот спор о терминах. Называй как хочешь — суть то от этого не меняется.
К тому чтобы уципиться за явно ошибочное утверждение и на этом фоне поставить под сомнения утверждения которые он не может опровергнуть, но котрые ему не нравятся. Можно назвать этот приемом как угожно, но он "прошел на ура"... И не в первый раз... К сожалению.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> Примеры в студию, того что нельзя сделать на дженириках и при этом это не относится к метапрограммированию.
Нельзя использовать все возможности языка (того же C# в данном случае). Например, использовать перегруженные операторы, статические методы, конструкторы с аргументами. Последнее ограничение, например, не позволяет сделать шаблон фабрики. Первое — даже простейший шаблон accumulate.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Чтобы не углубляться в очередной терминологический спор, сформулируем просто: в шаблонах C++ можно использовать все возможности языка C++, в C# generics все возможности языка C# использовать нельзя. Т.е. часть алгоритмов, которые можно на C# написать, обобщить до generics не получится. С шаблонами C++ таких проблем нет.
Это просто разные по своей сущности вещи. Общего в них лишь использование угловых скобок.
Щас снова скажу крамолу (вах, боюс-боюс).
Шаблоны по своей сути — это макросы, какими бы умными "метапрограммированиями" их ни обзывали. Конечно, это не сишные define-макросы, они гораздо мощнее — хотя бы тем, что их можно нормально (иногда!) трассировать в отладчике. Но в этом-то и проблемы тоже — ужасающие сообщения об ошибках компиляции. Чего бы там ни говорили, но человек — не компилятор и "вкурить" сообщение длиной в килобайт — иногда повеситься можно. Кстати, это не просто так нельзя использовать что-то типа
Если такое разрешить, то на адекватном трассировании сразу можно ставить жирный крест — возвращаемся к базотладочным временам лог-файлов.
Генерики полностью свободны от недостатков шаблонов, поскольку принципиально runtime. Но ведь они и не дают ничего существенного. Как было убедительно показано, они — всего лишь автоматизация dynamic cast. Типа просто надо было придумать некий "наш ответ Страуструпу — мы тоже умеем использовать угловые скобки"
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
VladD2,
> ПК>Именно о "напрямую" и идет речь. > > Я не понял. Тебя интересуют качественные возможности или фишки? Другими словами тебе фишечки нужны или ехать?
Нужно ехать: нужно, чтобы клиент не копипэйстил x + y в своем коде, а это было сделано один раз в шаблоне.
> ПК>Теперь, пожалуйста, сделай generic вариант вот этих вот двух функций, чтоб не нужно было делать copy-paste для каждого нового типа. Что, не получается? То-то. Об этом и речь. Вот вариант в виде шаблона: > ПК>
> ПК>template<class T>
> ПК>static T Add(T x, T y) { return x + y; }
> ПК>
> А у тебя получится?
С generics? Нет, и у меня не получится. Поэтому и говорю, что они этого не позволяют.
> Если тип новый, то и методы у него нужно писать новые. Вот и пиши методы, а уже их вызывай из операторов.
Не годится. Класс уже написан, не нами. Например, это int.
> Ну, да ради искуства... напишу тебе универсальную функцию : >
> static Adder<T> GetAdditionOperator<T>()
> {
> return (Adder<T>)Delegate.CreateDelegate(
> typeof(Adder<T>), typeof(T), "op_Addition");
> }
> ...
> TimeSpan timeSpanValue = Accumulate<TimeSpan>(
> GetAdditionOperator<TimeSpan>(),
> new TimeSpan[]
> {
> new TimeSpan(10, 0, 0), new TimeSpan(10000),
> new TimeSpan(1, 12, 10), new TimeSpan(20000)
> });
> Console.WriteLine("timeSpanValue is " + timeSpanValue);
>
> На жлабэйские операторы и вовсе доступны в виде методов.
Ерунда. Просто место copy-paste изменилось. Где само x + y, там и copy-paste.
> ПК>Ага, с песней. Для каждого типа. > > О, блин, проблема! Ты еще не забыл, что это можно просто по месту делать? Анонимные методы еще ведь никто не отменял: >
> Xxx(delegate(int i) { return new Yyy(i) });
>
Это означает, что клиенты моего "generic" класса будут в своем коде делать copy-paste для каждого нового типа, с которым они мой "generic" класс захотят использовать. Или, если "по месту", то не для каждого типа, а в месте каждого вызова.
> Да и это ты уж совсем из пальца проблемы высасывашь. На практике такие изыки встречаются крайне редко. А фабрики классов обычно делаются на базе активатора, так как в отличии от плюсов все компоненты и любой класс можно создать динамически. С точки зрения фабрики классов намного выгоднее прописать все что нужно в файле настроек и создавать классы по этим описаниям.
Ага. Например, создание таким макаром результата функции получения ряда матрицы... Представляю
> Ты еще не забыл, что я тут в основном против твоего заялления о бесполезности дженериков спорю
Не о бесполезности, а об отсутствии у них достоинств шаблонов.
> Я где-то сдублировал код? Или выдавать желаемое за действительное начинает входить в привычку? Как в прочем и желание найти проблему даже там где ее нет. В примере дублируются только строчки "x + y". И понятно почему. Дженерики не макросы. <...>
Я отлично понимаю, почему именно так происходит. Тем не менее copy-paste остается. И чем сложнее будет generic функция (чем больше ей будет нужно операторов), тем больше этого дублирования будет.
> Не... я был бы только за если бы появились констрэйны типа "+" или "-". Но и без них особых проблем нет.
Это потому что ты математику на generics писать не пытался.
> Вот к С++ претензий хоть отбавляй. Попробуй ради хохмы передать ссылку на метод по сети. Получишь гору фрэймворков вроде КОМ или КОРБА и море геморроя.
VladD2,
> ПК>На уровне возможностей generics? Пишешь обычный класс + шаблон-обвязку, приводящую аргументы и результаты функций. Класс экспортируется, шаблон включается обычным #include. Все, справился. > > Ну, тоесть нельзя? Шаблон инклюдами... дальше уже можно не продолжать. Если хоть один метод с параметром типа скомпилирован, то новых специализаций уже не породить.
Легко. Они будут порождаться клиентом. "Рабочий" код будет в .dll.
> А можно узнать что нового привносят в данном разрезе шаблоны?
Кроме переноса диагностики в статуку — замена copy-paste. Везде, где нужно было копировать код, можно заменить это на шаблон. Generics полностью эту задачу не решают.
> ПК>Разными. Параметрический полиморфизм (aka основной инструмент обобщенного программирования) позволяет писать код идентичным образом для разных типов. Generics ограничивают множество конструкций до тех же, что доступны в "обычных", не generic, классах.
> Чушь какая. Все что ты пишашь на шаблонах можно написать и в с использованием динамического полиморфизма и приведений типов.
>>> >>> И? Опять млкие ужимки. > > ПК>Не хами. > > Какое фамство? Ты уже часа 4 откровенно называшь белое черным и пыташся найти какие-то зацпки для обоснования этого. Мне это уже порядком надоело.
Можно и по-другому повернуть: ты уже 4 часа откровенно не понимаешь, где черное, а где белое, да еще и хамишь. Мне это уже порядком надоело.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VladD2,
> ПК> Ага. Не работает. Методы такие: +, -, *, / и т.п., т.к. generic алгоритм должен работать и со встроенными типами.
> Опять же интерейс тебе поможет. Кто скзал, что его нужно реализовывать в типе?
Я сказал. Эти типы должны быть удобны в использовании и без шаблонов. Плюс это все хозяйство должно работать со встроенными типами и с типами из сторонних библиотек.
> Сделай хэлпер. Ты же в С++ передаешь через параметр разные Аллокаторы и т.п.
Я о них забочусь только когда они мне нужны (в частности аллокаторы — три или четыре раза за все время). В остальных случаях они под руками не мешаются, т.к. их явно указывать не нужно. С generics это не пройдет: там все нужно будет делать явно, т.к. даже специализаций нет.
> ПК>
> ПК>Будет работать для любых скаляров T, начиная от int, float и заканчивая MyBigInt, MyRational, MyDecimal и т.п. В пример включен подразумеваемый шаблон Vector3<T> и т.п.
> 1 в 1 можно сделать на шарпе. Только вместо операций будут методы или объект-хэлпер. Разницы никакой.
Методы чего? А если это не оператор *, а вспомогательная функция, которая не может быть членом Vector3<>, т.к. этот класс в библиотеке, а функция — в моем приложении? В C# не будет работать потому что: нельзя вызвать * для T, нельзя вызвать конструктор для Vector3<T>.
> ПК> Впрочем, отсутствие необходимости в boxing/unboxing можно тоже добавить, но это уже речь об оптимизации, а не о возможностях.
> А о чем еще можно говорить если речь зашла о скорости кода?
Речь о скорости кода завел ты. Я говорил о возможностях, направленных на облегчение повторного использования кода.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VD>Тут и параметризация константами,
Ну и что? Или если этого нет в генериках, то оно автоматически сразу становится метопрограммированием?
VD>и изменение структуры кода при изменении параметра типа.
Семантически код абсолютно не меняется. То, что там происходит на уровне ассемблера, мне по барабану.
VD>Натуральная кодогенерация. И потому легко решается с помощью макросов и кодогенераторов.
А list<T> — это тоже натуральная кодогенерация? Ведь оно тоже "легко решается с помощью макросов и кодогенераторов"?
VD>В отсуствии необходимости применения боксинга, наследования, виртуальных методов. В применимости к вэлью-типам. В общем, во всем в том, что касается и шаблонов. В итоге статическая типобезопастность и повешение скорости.
Ага, то есть ты признаешь, что с семантической точки зрания генерики не привносят ничего, кроме отсутствия необходимости делать приведения типов, а все их остальные бонусы сводятся к оптимизации?
Ну если так, то я напомню, что возможности по оптимизации, предоставляемые генериками — это просто ДЕТСКИЙ САД, по сравнению с оптимизацией на шаблонах! Надеюсь, это доказывать не придется?
VladD2,
> ПК> Нет, код может быть в DLL, а в заголовочном файле — только переходники для "автоматического" приведения типов.
> Понятно. Пошли выдумывать неотносящиеся к делу случая чтобы оправдать свои слова. Мы вроде говорили об экспорте шаблона из библиотеки. Ну, и не нужно сваливаться на необобщенные интерфейсы. Они тут не причем.
Таким образом есть разница между опосредованным экспортом и непосредственным?
> ПК> В C++ шаблоны дают возможность работать с арифметическими типами полиморфно. Generics в C# — нет.
> Создай обертку над типом и предстваь все операции в виде методов. <...>
Иными словами ты в очередной раз предлагаешь мне использовать арифметические типы в обобщенных алгоритмах опосредованно. Спасибо, не надо — уже, кажется, говорил.
> Это на любом языке поддерживающем полиморфизм можно сделать. Хоть на С.
Совершенно верно. Именно это я и имел в виду, говоря о том, что generics лишены большинства достоинств шаблонов.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, VladD2, Вы писали:
VD>По определению.
Обобщение — это абстрагирование от частностей. Если так, то я не понимаю, почему же можно абстрагироваться от конкретных типов, а вот абстрагироваться от конкретных констант партия запрещает? Почему обобщать по типам можно, а обобщать по константам нельзя? Неужели, это все потому, что так написано в энциклопедии?
Здравствуйте, prVovik, Вы писали:
VD>>Тем что дженерики можно положить в длл и использовать их без исходников прямо в бинарном виде. А шаблоные нельзя. V> Так, еще разок: V>
При этом, весь реально работающий код находится в длл, которую можно менять.
Вот это сказка.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
V>>То есть, таким образом, мы получили статический контроль типизации нетипизированной динамически загружаемой библиотеки.
VD>Это, я извинясь, хрень полная, а не шаблон в библиотеке. Что и следовало доказать. В то же время дженерики лежат себе в библоиотеках и даже описания текстового не просят. Потому как проектировались в рассчете на это.
Чтобы использовать extern "C" функцию, определенную в dll, тоже нужно текстовое объявление. И это не мешает их широкому использованию.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>VladD2,
>> ПК> Влад, не смешно. Перечитай предлагавшиеся варианты (выше по ветке). Т.к. generics ограничены возможностями работы через интерфейсы, то можно вынести соответствующие non-generic функции, работающие через ссылки и указатели на интерфейсы, в DLL. Что конкретно не будет работать?
>> Ничего не будет работать. Положить полноценный шаблон в длл невозможно. А дженерик раз плюнуть.
ПК>Полноценный, естественно, не получится. А неполноценный, типа generics, как уже показали — легко
Ну, это бездоказательные наезды. Основанные на извращении фактов и желании выдавать желаемое за действительное. Достичь возможностей дженериков при условии хранения в бинаром виде шаблонами неудастся. Для дженериков как и шаблонов, если в качестве параметров использовать вэлью-типы, создаются отдельные специализации. Вот только для шаблонов специализации создает компилятор, так что в библиотеке может быть только конченый их набор. А для дженериков специализации создает джит или ngen. И никаких противопоказаний для порождения специализацих даже на лету нет.
ПК> Наличие переходников в заголовках не считается, если ты предлагаешь не считать количество делегатов для передачи операторов в generics: баш на баш, так сказать
Короче, как только тебе удастся запихнуть в ДЛЛ скажем std::vector<>, то можно будет продолжить — это спор. А до тех пор он несколько не сотоятелен.
Нежелание тобой, и другими слишком привязавшимися к плюсам личностями, факта полноценности дженериков ни сколько не понижают их полноценноси. Это скрее характиризует этих личностей.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали: ПК>Извиняюсь, что посреди большой философии с такими частностями. Тем не менее...
Очень жду
>> Читал, что экспорт шаблонов ещё не сделан. ПК>Сделан в EDG. Сравнительно давно доступен в Comeau.
>> Нужен? "Необходим!" ответят, я думаю, многие. ПК>Уверяю, не необходим. Кой-какая польза от него есть, но не принципиальная. Заключается в том, что при наличии экспорта шаблонов можно перекомпилировать не все файлы, зависящие от определения изменившегося шаблона, а только один из них. Имхо, намного полезнее введение модулей, чему, впрочем, экспорт шаблонов, вроде, не мешает.
Эх, а я думал можно будет их в библиотеки вставлять и отдавать только хидер... Но! не подсказывайте больше, я сам
ПК>Хотя, согласен, практического опыта использования экспорта шаблонов пока наработано немного, может оказаться, что какие-то дополнительные бонусы еще не найдены.
Спасибо, с этим я понял. Куда ещё можно "углубить" С++? вот что мне интересно. Когда увидел книжки про колдовство с шаблонами стало ясно что их ещё изучать и изучать (не только мне но и "Говорителям Об") — но, мне кажется, это всё-таки "вширь", а "вглубь" — это новое, а не изучение имеющегося.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Павел Кузнецов, Вы писали: ПК>>Извиняюсь, что посреди большой философии с такими частностями. Тем не менее... _FR>Очень жду
Эх! смайликом обшибся. На сомом-то деле я _FR> Очень жду
Help will always be given at Hogwarts to those who ask for it.
AndrewVK,
> _FR> Эх, а я думал можно будет их в библиотеки вставлять и отдавать только хидер...
> C++ные шаблоны нельзя скомпилировать принципиально. Для компиляции нужно нечто вроде нетовских дженериков.
Это не так. Скомпилировать шаблоны до уровня распространения в виде статических библиотек вполне возможно. Естественно, это не будут "обыкновенные" .obj-файлы, но и сборки .Net ими тоже не являются. В общем, относительно компиляции шаблонов в промежуточный код, вопрос в том, настолько ли это нужно, чтобы этим заниматься, т.к. хранение шаблонов в промежуточном виде требует серьезных дополнительных усилий по сравнению с хранением шаблонов в их первичной, текстовой форме.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали: >> _FR> Эх, а я думал можно будет их в библиотеки вставлять и отдавать только хидер... >> C++ные шаблоны нельзя скомпилировать принципиально. Для компиляции нужно нечто вроде нетовских дженериков. ПК>Это не так. Скомпилировать шаблоны до уровня распространения в виде статических библиотек вполне возможно. Естественно, это не будут "обыкновенные" .obj-файлы, но и сборки .Net ими тоже не являются. В общем, относительно компиляции шаблонов в промежуточный код, вопрос в том, настолько ли это нужно, чтобы этим заниматься, т.к. хранение шаблонов в промежуточном виде требует серьезных дополнительных усилий по сравнению с хранением шаблонов в их первичной, текстовой форме.
Спасибо, об этой возможности я даже не слышал. Позавчера просто вечером тоска навалилась и принялся дочитывать журнал. Между явой а дельфи попал на эту статью Шаблоны и модули
. В статье сказано, в частности, "Таким образом, большинство современных компиляторов C++ не позволяет "делить" шаблоны на части и транслировать отдельно.", в чём мне повезло задолго до прочтения убедиться. И на слово "практически" в самом последнем примечании я если и обратил внимание, то сегодня уже не вспомнил. В контексте статьи я и сделал смелый и неправильный вывод. Учту.
Скорость компиляции меня давно уже не беспокоит (в контексте топика позвольте умилиться запуску VS 6.0 на 486 с 15 Мб памяти и 20 на диске ).
Кстати о скорости. Начал замечать за собой такую неприятную ( ) особенность — вместо того чтоб десятый раз пробежаться глазами по строкам, руки тянутся нажать Build и сразу получить все (ну конечно же не все, но...) ответы. Не те ли это синдромы, от которых предостерегает SchweinDeBurg? А?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Павел Кузнецов, Вы писали:
>> C++ные шаблоны нельзя скомпилировать принципиально. Для компиляции нужно нечто вроде нетовских дженериков.
ПК>Это не так. Скомпилировать шаблоны до уровня распространения в виде статических библиотек вполне возможно. Естественно, это не будут "обыкновенные" .obj-файлы, но и сборки .Net ими тоже не являются.
Естественно в такой постановке возможно. Можно например исходники запаковать .
На самом деле вопрос в том что такое компиляция. Плюсовые шаблоны нельзя обработать дальше AST и при экспорте максимум что можно сделать это сохранить его в бинарном виде. Все равно компилятору (именно компилятору, а не линкеру) потом придется с этими шаблонами работать. А вот в дотнете дженерики именно скомпилированы, там нормальный IL-код внутри. Это примерно как если бы в С++ шаблон можно было бы запихать в dll, да так чтобы при смене этой dll поведение программы изменилось без перекомпиляции использующего кода. Для плюсов это невозможно, поскольку невозможно до развертывания шаблона определить токен используемых методов (адрес статического метода, номер слота виртуального и т.п.).
Какие от этого бенефиты? Вобщем то вполне очевидные:
1) Нормальная работа в компонентной среде, возможность создания дженерик-компонентов.
2) Быстрая компиляция. Наличие в проекте дженериков практически не влияет на скорость компиляции.
3) Нормальная работа Intellisence, рефакторинга. Нормальная диагностика ошибок.
4) Отсутствие дублирования кода в скомпилированных модулях.
5) В условиях managed-языков — меньше нагрузка на JIT.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>AndrewVK,
>> _FR> Эх, а я думал можно будет их в библиотеки вставлять и отдавать только хидер...
>> C++ные шаблоны нельзя скомпилировать принципиально. Для компиляции нужно нечто вроде нетовских дженериков.
ПК>Это не так. Скомпилировать шаблоны до уровня распространения в виде статических библиотек вполне возможно. Естественно, это не будут "обыкновенные" .obj-файлы, но и сборки .Net ими тоже не являются. В общем, относительно компиляции шаблонов в промежуточный код, вопрос в том, настолько ли это нужно, чтобы этим заниматься, т.к. хранение шаблонов в промежуточном виде требует серьезных дополнительных усилий по сравнению с хранением шаблонов в их первичной, текстовой форме.
Думаю, что это было бы полезно, поскольку это помогло бы ускорить процесс инстантинации шаблонов. Насчет дополнительных усилий. При разборе заголовка с шаблонами, компилятор всё равно переводит их в некоторое внутреннее представление, работа с которым, естественно, более эффективна, чем с исходных текстовым. Всё что нужно -- сериализовать это представление в бинарную форму. Это достаточно стандартная задача.
Здравствуйте, AndrewVK, Вы писали: >>> C++ные шаблоны нельзя скомпилировать принципиально. Для компиляции нужно нечто вроде нетовских дженериков.
[skipped] AVK>Какие от этого бенефиты? Вобщем то вполне очевидные: AVK>1) Нормальная работа в компонентной среде, возможность создания дженерик-компонентов. Угу
Шахтер,
> ПК> В общем, относительно компиляции шаблонов в промежуточный код, вопрос в том, настолько ли это нужно, чтобы этим заниматься, т.к. хранение шаблонов в промежуточном виде требует серьезных дополнительных усилий по сравнению с хранением шаблонов в их первичной, текстовой форме.
> Думаю, что это было бы полезно, поскольку это помогло бы ускорить процесс инстантинации шаблонов.
Кто-то из EDG (по-моему, Вандевурд или Адамчик) где-то когда-то (*) писал, что их эксперименты показали, что особого ускорения замечено не было.
> Насчет дополнительных усилий. При разборе заголовка с шаблонами, компилятор всё равно переводит их в некоторое внутреннее представление, работа с которым, естественно, более эффективна, чем с исходных текстовым. Всё что нужно -- сериализовать это представление в бинарную форму. Это достаточно стандартная задача.
Кроме этого шага есть еще, например, выдача диагностики, которую во многих реализациях намного легче осуществлять, имея в распоряжении исходный код.
(*) кто-то ... где-то ... когда-то ... — согласен, неточностей многовато, но искать кто, где и когда конкретно, честно говоря, лень
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Кто-то из EDG (по-моему, Вандевурд или Адамчик) где-то когда-то (*) писал, что их эксперименты показали, что особого ускорения замечено не было.
Вполне предсказуемо. Парсинг исходников далеко не самая медленная операция, на ней много не съэкономишь.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Шахтер,
>> ПК> В общем, относительно компиляции шаблонов в промежуточный код, вопрос в том, настолько ли это нужно, чтобы этим заниматься, т.к. хранение шаблонов в промежуточном виде требует серьезных дополнительных усилий по сравнению с хранением шаблонов в их первичной, текстовой форме.
>> Думаю, что это было бы полезно, поскольку это помогло бы ускорить процесс инстантинации шаблонов.
ПК>Кто-то из EDG (по-моему, Вандевурд или Адамчик) где-то когда-то (*) писал, что их эксперименты показали, что особого ускорения замечено не было.
Ну, еджиссонам виднее.
>> Насчет дополнительных усилий. При разборе заголовка с шаблонами, компилятор всё равно переводит их в некоторое внутреннее представление, работа с которым, естественно, более эффективна, чем с исходных текстовым. Всё что нужно -- сериализовать это представление в бинарную форму. Это достаточно стандартная задача.
ПК>Кроме этого шага есть еще, например, выдача диагностики, которую во многих реализациях намного легче осуществлять, имея в распоряжении исходный код.
ПК>
ПК>(*) кто-то ... где-то ... когда-то ... — согласен, неточностей многовато, но искать кто, где и когда конкретно, честно говоря, лень
Вообще, это довольно интересная тема. Если действительно нет особого ускорения, то это значит, что фаза парсинга занимает небольшую долю времени в процессе компиляции, а основную -- как раз фаза кодогенерации, которую нельзя сократить создавая бинарное представление шаблона.
Здравствуйте, AndrewVK, Вы писали:
Ш>>Нет никакого "дублирования кода" в шаблонах. Код, сгенерённый из шаблона для существенно разных параметров приципиально разный.
AVK>Да? А если мы возьмем обыкновенные контейнеры? Там именно что дублирование — разница только в адресах функций и размерах оперируемых данных.
Да? А не освежить ли тебе память и не посмотреть ли на то, как устроен итератор по вектору и по списку?
Здравствуйте, AndrewVK, Вы писали: _FR>>Ага! Значит у всех в С++ шаблонах оно не работает AVK>Нет, нормально не работает. А ты не знал?
Наблюдал, но думал что я их как-то неправльно использую, что надо бы залезть куда-нить в AUTOEXP.DAT и там поковыряться.
По большому счёту кроме коллекций МФЦ ни с чем дела не имел, кинул взгляд на "Modern C++ Design" и стал мечтать посвятить отпуск этому Чуду.
Не потому что так хочется применять, но хочется знать, самому так научиться. Потому что удивительно.
_FR>> И, к слову, сильно ещё сама среда не готова к дженерикам. AVK>Какая среда?
Извини, не ясно высказался. Среда разработки. Whidbey. Столкнулся с парой неприятных моментов, но, к стыду своему, пока не нашёл времени попросить помощи в подготовке репорта в feedback.
AVK>>>5) В условиях managed-языков — меньше нагрузка на JIT. _FR>>Да, но отсюда же и некоторые их недостатки? AVK>Разумеется. Но надо понимать главное — с синтаксическими шаблонами ни о какой компонентности речи уже не и дет. ИМХО для дотнета это смертельный недостаток, поскольку коллекции, которые нельзя передавать между компонентами резко теряют в своей привлекательности. А для метапрограммирования я думаю нужно что нибудь попривлекательнее шаблонов.
Да! Это другое. Ну почему, например, не позволить, сделать такие мелочи, как, например, отдельное именование ограничения/уточнения? Я, может, слишком рьяно за них взялся, но уже это становится актуальным, или позволить using (directive) внутри класса — ведь снаружи к защищённым вложенным типам не очень-то доберёшся, а в каждой указывать OrderedDioctionary<MyPrivateClassName> некошерно.
Но я почемуто из-за этого от них не отворачиваьсь и борюсь как могу (может всё-тки Александреску и Ко поситать )
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, Шахтер, Вы писали:
Ш>>Думаю, что это было бы полезно, поскольку это помогло бы ускорить процесс инстантинации шаблонов. Насчет дополнительных усилий. При разборе заголовка с шаблонами, компилятор всё равно переводит их в некоторое внутреннее представление, работа с которым, естественно, более эффективна, чем с исходных текстовым. Всё что нужно -- сериализовать это представление в бинарную форму. Это достаточно стандартная задача.
MS>Щас я такое выдам... MS>На самом деле, форма хранения не важна. Проблема C++ в том, что все стараются придерживаться замшелой парадигмы о раздельной компиляции.
Да. Но не совсем так. Дело ведь не в том, что придерживаются. А в том, что очень трудно технически перескочить с этого подхода на полностью модульный подход. Особенно в каких-нибудь юниксах. А, кроме того, всё ещё очень нужна интеграция со старым кодом, старыми библиотеками и.т.д. Да и какой-нибудь работающей по-новому реализации пока нет. Так что это вопрос достаточно большого времени, я думаю. Наследство давит. И миллиарды, как Майкрософт, в развитие тут не вкладывают.
AndrewVK,
> Ш> Это достигается за счет очень серьёзных ограничений на возможности дженериков. Для шаблонов это неприемлимо.
> Никаких ограничений на выполнение основной задачи дженериков — дженерик программирования, это не накладывает.
Зависит от используемого определения generic программирования. Однако отрицать, что из generics доступны далеко не все возможности C# не приходится. Например, использование перегруженных операторов и (если не ошибаюсь) статических методов.
> Что же касается возможностей метапрограммирования — плюсовые шаблоны это один из худших вариантов, который можно придумать.
Можно ограничить рассмотрение только "обычным" generic программированием. Проблема только в том, что определить грань между generic программированием и метапрограммированием далеко не всегда легко.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Шахтер, Вы писали:
AVK>>Да? А если мы возьмем обыкновенные контейнеры? Там именно что дублирование — разница только в адресах функций и размерах оперируемых данных.
Ш>Да? А не освежить ли тебе память и не посмотреть ли на то, как устроен итератор по вектору и по списку?
возьмем обыкновенные контейнеры
Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование. Итераторы как раз и есть метапрограммирование.
Здравствуйте, _FRED_, Вы писали:
_FR>>> И, к слову, сильно ещё сама среда не готова к дженерикам. AVK>>Какая среда? _FR>Извини, не ясно высказался. Среда разработки. Whidbey. Столкнулся с парой неприятных моментов, но, к стыду своему, пока не нашёл времени попросить помощи в подготовке репорта в feedback.
VS 2005 еще очень сырая и дело далеко не только в дженериках.
_FR>Да! Это другое. Ну почему, например, не позволить, сделать такие мелочи, как, например, отдельное именование ограничения/уточнения?
AndrewVK,
> Я понимаю, что есть случай, когда дублирование оправдано. Но ровно так же есть случаи, когда оно не оправдано. И если внимательно на такие случаи посмотреть, то это окажется как раз то самое метапрограммирование. Итераторы как раз и есть метапрограммирование.
Ты, похоже, пользуешься каким-то уж очень нетрадиционным определением метапрограммирования.
А функция find() в этих "обыкновенных" контейнерах Vector и List тоже "будет метапрограммированием"? Если нет, чем она отличается от итераторов? Если да, то я вообще не понимаю, где в твоей трактовке грань между generic программированием, и метапрограммированием.
Если мы уберем из контейнеров итераторы, то, по-видимому, придется добавить индексацию (operator []). Индексация тоже "будет метапрограммированием", или нет?
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, AndrewVK, Вы писали: _FR>>>> И, к слову, сильно ещё сама среда не готова к дженерикам. AVK>>>Какая среда? _FR>>Извини, не ясно высказался. Среда разработки. Whidbey. Столкнулся с парой неприятных моментов, но, к стыду своему, пока не нашёл времени попросить помощи в подготовке репорта в feedback. AVK>VS 2005 еще очень сырая и дело далеко не только в дженериках.
Мирюсь :о)
_FR>>Да! Это другое. Ну почему, например, не позволить, сделать такие мелочи, как, например, отдельное именование ограничения/уточнения? AVK>Это как?
Вот есть у меня набор классов, взаимодействующих друг с другом, но не связанных "родственными отношениями".
Что-то на подобии O\R Mapping'а. Есть базовай класс Entity. Всё, что нужно от него остальным — его идентификотор.Может быть int, или Guid, или даже составным (из нескольких полей). Объявил я его примрно так:
public abstract class BizEntity<IdentiferType>
where IdentiferType : struct, IComparable<IdentiferType>
{
//...
// По сути всё, что внешний мир должен о нём знатьpublic IdentiferType EntityID {
get {
}
}
//...
}
CLRовские типы этим условиям удовлетворяют, будет составной ключ — напишу свою структуру под него и реализую нужный интерфейс.
Соответственно все классы, так или иначе с ним связанные, тащут за собой этот "хвост" из IdentiferType : struct, IComparable<IdentiferType>. А вдруг мне понадобится какой ещё интерфейс у этой структуры? Надо будет всё облазить и всё поправить.
Например, метод, который мне эту сущность должен вернуть такой получается:
public class BizEntityManager<IdentiferType> where IdentiferType : struct, IComparable<IdentiferType>
{
//...
E Load<E, IdentiferType>(IdentiferType ID)
where E : BizEntity<IdentiferType>
where IdentiferType : struct, IComparable<IdentiferType>
{
}
//...
}
Примерно так, если в синтаксисе нигде не запутался
Требуется что-то, даже на подобии юзинга, чтоб в каждом файле даже объявлять, что
using constraint IdentiferTypeC = struct, IComparable<IdentiferType>
public abstract class BizEntity<IdentiferType> where IdentiferType : IdentiferTypeC
{
//...
// По сути всё, что внешний мир должен о нём знатьpublic IdentiferType EntityID {
get {
}
}
//...
}
Хоть бы так.
Это "заставь дурака Богу мольться..." или нет?
Help will always be given at Hogwarts to those who ask for it.
Шахтер,
> И ещё. Обобщённое программирование потому так и называется, что позволяет абстрагироваться от деталей устройства того или иного типа и использовать его абстрактные свойства и поведение. Одинаковый код при этом получится никак не может.
Извини, немного уточню: может, но не должен
> Если при использовании дженериков получается один и тот же MSIL код, то это означает только одно -- никаким обобщённым программированием там и не пахнет, максимум что там есть -- старый банальный полиморфизм (поданый под новым соусом).
У меня тоже сложилось похожее ощущение. Насколько я понимаю, generics от "банального полиморфизма" в C# отличаются (только) тем, что позволяют лучше контролировать соответствие типов во время компиляции, плюс позволяют избегать множества приведений типов, в противном случае неизбежных без написания своих переходников к контейнерам и т.п.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ничего подобного. Итераторы программой как данными не оперируют. Более того, ничего принципиально декларативного в них тоже нет: ПК>
ПК>std::vector<int> v( 10 );
ПК>for (std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i)
ПК> *i = e - i;
ПК>
ПК>самая что ни на есть итеративная программа.
Сам итератор декларативно задает некий алгоритм. Натуральная метапрограмма.
Здравствуйте, McSeem2, Вы писали:
MS>Шаблоны в C++ — ужасны. Но что-то пока не видать ни одного другого языка программирования, в котором было бы что-то подобное, с такой же свободой выражения мыслей и такой же эффективностью кода. С++ — язык свободы, за что он и снискал всеобщую любовь и всеобщую ненависть.
Подобные заявления попадают под категорию (цитируя классика) "космического масштаба и космической же глупости о том, как все поделить".
То что ты не знаешь языков гибче С++ еще не значит что их не существует. Например OpenC++ по гибкости на порядок круче С++.
Здравствуйте, AndrewVK, Вы писали:
AVK>То что ты не знаешь языков гибче С++ еще не значит что их не существует. Например OpenC++ по гибкости на порядок круче С++.
Фактически, если я о них не знаю, это как раз и означает, что их нет. Это все делается на уровне доморощенного энтузиазма, так же, как мой AGG или R#. До стандартизации и промышленного применения — ох как далеко. Короче говоря, здесь я больше верю в дот-нет, чем в OpenC++.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Шахтер, Вы писали:
Ш>Дело ведь не в том, что придерживаются. А в том, что очень трудно технически перескочить с этого подхода на полностью модульный подход.
На самом деле, не так уж и трудно. Достаточно научить компилятор понимать формат OBJ-файлов и линковать в бинарный код. При этом, чисто Сишые (или Фортрановсеие) obj-файлы точно так же могут быть подключены к списку трансляции. При этом, тот самый единый модуль "компилинкер" имеет право транслировать и подключать шаблоны. Никаких технических препятствий для этого я не вижу. Единственная причина — традиции
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Павел Кузнецов, Вы писали:
>> В этом случае все без особых проблем реализуется на шарпе.
ПК>Ну и что?
А то, что исходная мысль была о том, что большинство отличий в возможностях шаблонов имеют практическое значение при метапрограммировании, а не при дженерик-программировании. Сам по себе итератор конечно не метапрограмма, но такой же итератор реализуется и на шарпе. Метачастью является функциональный стиль использования итератора — не выполняющий реальной работы, зато улучшающий синтаксис применения.
Здравствуйте, Павел Кузнецов, Вы писали:
>> исходная мысль была о том, что большинство отличий в возможностях шаблонов имеют практическое значение при метапрограммировании, а не при дженерик-программировании.
ПК>Эта мысль не совсем верна. В том смысле, да некоторая часть отличий относится к метапрограммированию, но итераторы к этому никаким боком, пожалуй, как и очень многое из "большинства" отличий шаблонов С++ от C# generics.
Еще раз — речь не про отличия, речь про возможности. А отличие там кардинальное — дженерики и шаблоны работают на разных уровнях. Два различных способа получения одного результата.
ПК> Но это просто стиль, не метапрограмма.
Метапрограмма это код, преобразующий изначально неподдерживаемый С++ функциональный стиль в классический императивный. Т.е. синтаксически корректный, но семантически непонятный стиль при помощи шаблона преобразуется в понятную кодогенератору форму. Проблема в том что многие это воспринимают как нечто уникальное и близкое к идеалу.
ПК>Об улучшении же синтаксиса применения... Если пойти по этой дорожке достаточно далеко, то мы дойдем до того, что все языки программирования высокого уровня по большому счету являются не более чем syntactic sugar над ассемблером.
Если выкинуть рантайм. А так да — большинство фич С++ и многие фичи C# можно трактовать как "не более чем syntactic sugar над ассемблером".
ПК>И, хотя по большому счету мне все равно, назовешь ли ты такой стиль программирования "улучшением синтаксиса применения", т.к. мне и другим, кто его предпочитает, это помогает быстрее и с большим удовольствием писать более понятные (*) и более легко сопровождаемые (**) программы, все же замечу, что грань между "улучшением синтаксиса" и "выполнением работы" на первый взгляд подчас бывает очень тонкой.
Ты опять мою мысль не понял. Мне пофигу как это называть. Речь о другом — достижение подобного при помощи шаблонов очень фиговый способ. Более правильным было бы наличие чистых дженериков без побочных эффектов + специализированные средства метапрограммирования, как например в OpenC++, XC#, R# наконец. Вот только чтобы это была стандартная фича языка, а не стороннее средство.
ПК>Например, for each в C# — это улучшение синтаксиса или не только?
Улучшение синтаксиса.
ПК> А перегрузка функций?
Тут не понял. Перегрузка функций это скорее отсутствие запрета, нежели нарошная фича. Если же речь не о перегрузке как таковой, а о статическом полиморфизме, с этим связанном, то да, это именно что синтаксис.
ПК> А неявный боксинг?
А это уже фича рантайма.
ПК> А операторы + — и т.п. вместо функций Add, Substract и т.п.?
Чисто синтаксическая фича к сожалению.
ПК> А properties? А enums?
Поддерживается рантаймом.
ПК> А цикл for (ведь достаточно while)?
Тоже синтаксис. В IL никакого for нет. Офф: знаешь откуда синтаксис for взялся? Практически 1 в 1 скопированно с соответствующего макроса макроассемблеров.
ПК> А оператор switch (ведь достаточно (if ... else if ...)?
Смотря какой.
ПК> Если зайти достаточно далеко, то C# generics почти целиком можно списать на улучшение синтаксиса,
Дженерики нельзя — нужна довольно серьезная поддержка рантайма.
ПК> т.к. значительная их часть сводится к автоматизации приведения типов.
Не все так просто. Достаточно вспомнить к примеру о том что дотнет на 100% динамически типизированный.
А вобще я не понимаю к чему этот спор о терминах. Называй как хочешь — суть то от этого не меняется.
ПК>Имхо все это неверно, т.к. все эти вещи, равно как и многие отличия шаблонов C++ от C# generics, позволяют использовать какие-то новые идиомы, и, соответственно, просто к "улучшению синтаксиса применения" не сводятся. По-моему, грань, отделяющая "улучшение синтаксиса" от "выполнения работы" как раз и лежит там, где добавление новых выразительных средств приводит к качественному изменению языка, давая пространство для новых идиом и стилей программирования.
Я тебе даже больше скажу — улучшение синтаксиса это тоже выполнение работы, поскольку доля тривиального (в смысле слабо смыслонаполненного) кода в современных программах все еще довольно высока. Мне не нравится использование для этой работы шаблонов, как впрочем и рантайм фишек в случае дотнета, поскольку плюсовые шаблоны приводят к страшно мутному коду и отвратительной работе интеллисенса сотоварищи, а рантайм решения дотнета иногда заметно сказываются на производительности и посему требуют более сложных алгоритмов для сохранения приемлемой эффективности. Но в любом случае — от отсутсвия плюсовых вывертов в дотнетных дженериках я не страдаю и даже этому рад.
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, Павел Кузнецов, Вы писали:
ПК>>Проблема только в том, что определить грань между generic программированием и метапрограммированием далеко не всегда легко.
MS>Точно! Может скажу и не в кассу, но слово "метапрограммирование" во мне до сих пор вызывает какой-то ступор, почти как "контрреволюция" — совершенно не понятно, что под ним скрывается. С этой точки зрения термин "generic" — гораздо более удачен. Есть сильное подозрение, что он рассчитан на профанов типа меня, не понимающих слова "метапрограммирование"
Купи книжку "C++ template metaprogramming", и всё поймёшь. Я недавно смотрел. Интереснейшая вещь. Там есть глава "Алгоритмы". Я думаю "ну, с алгоритмами я знаком". Не тут-то было. Там все те же концепции из STL, только ... в compile-time. Вектора, списки, итераторы, алгоритмы — всё над типами, всё в compile-time. Даже специальная глава про отладку есть... Мне теперь понятно стало, почему Александреску сейчас многопоточным программированием занимается.
<... прочитано внимательно, вырезано для краткости ...>
> ПК> А перегрузка функций? > > Тут не понял. Перегрузка функций это скорее отсутствие запрета, нежели нарошная фича. Если же речь не о перегрузке как таковой, а о статическом полиморфизме, с этим связанном, то да, это именно что синтаксис. > > ПК> А неявный боксинг? > > А это уже фича рантайма.
Похоже, я понял; у тебя разделение между "улучшением синтаксиса" и "выполнением работы" проходит по грани: поддерживатся ли данная "фича" языком или средой исполнения. Мне с такой дихотомией согласиться сложно.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Павел Кузнецов, Вы писали:
ПК>>Возможно, это субъективно, но в последнем случае у меня доверие к коду намного выше, чем если он был получен ковырнадцатью циклами compile & fix.
AVK>Зависит от задачи. Если задача вобщем то ясна, то я могу день писать код без компиляции (раньше использовал изредко, просто чтобы проверить синтаксис, но решарпер позволяет обходится без). А вот если пишешь скажем плагин к студии, то там без массы компиляций и отладки не проживешь, поскольку никакие напряжения мысли не помогут проникнутся особенностями поведения студийного API.
Не забудь добавить лом и такую-то матерь
Здравствуйте, AndrewVK, Вы писали:
AVK>Зависит от задачи. Если задача вобщем то ясна, то я могу день писать код без компиляции
ИМХО, это нехорошо, потому что трудно тогда баги искать.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ничего подобного. Итераторы программой как данными не оперируют. Более того, ничего принципиально декларативного в них тоже нет: ПК>
ПК>std::vector<int> v( 10 );
ПК>for (std::vector<int>::iterator i = v.begin(), e = v.end(); i != e; ++i)
ПК> *i = e - i;
ПК>
ПК>самая что ни на есть итеративная программа.
Тут я с тобой практически согласен. Вот только, это очередная зацепка за не осторожно сказанные слова, а не контраргумент по сути вопроса.
Чем, по-твоему, итераторы С++ отличаются от энумераторов дотнета?
public interface IEnumerator
{
bool MoveNext();
object Current { get; }
void Reset();
}
public interface IEnumerator<T> : IDisposable, IEnumerator
{
T Current { get; }
}
...
int sum = 0;
foreach (int elem in new int[]{ 2, 3, 5, 7, 9 })
sum += elem;
Просто, как всегда, С++ операется не на жетский интерфейс и его предварительное описание, а на сентаксическое соотвествие. В C# объект для использования в качестве итератора должен реализовывать интерфейс IEnumerator<T>, а в С++ поддерживать синтаксическую операцию сравнения и инкремента.
Так что АВК тут не прав, но приципились вы к его словам зря. По сути он совершенно прав. Все что могут шаблоны в области обобщенного программирования, все тоже самое могут и дженерики. Неподвластно им только лишь метапрограммирование. Но это не потому, что у тех кто их делал кишка тонка или мозгов не хватает. Прост они не хотели рождать уродцев подобных С++. Концепции должны быть чистыми. Как только появится красивая концепция метопрограммирования, хорошо интегрируемая в дотнет и Шарп, то она тот час же будет реализована.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ну и что? От этого действия, выполняемые итератором, равно как и вид результирующей программы ни на йоту не изменятся. Или все, что реализуемо на C++, но не реализуемо на C# является метапрограммированием?
А что в итераторах СТЛ не реализуется на Шарпе?
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, Павел Кузнецов, Вы писали:
>>> В этом случае все без особых проблем реализуется на шарпе.
ПК>>Ну и что?
AVK>А то, что исходная мысль была о том, что большинство отличий в возможностях шаблонов имеют практическое значение при метапрограммировании, а не при дженерик-программировании. Сам по себе итератор конечно не метапрограмма, но такой же итератор реализуется и на шарпе. Метачастью является функциональный стиль использования итератора — не выполняющий реальной работы, зато улучшающий синтаксис применения.
Чушь какая-то. Метапрограмма — это прграмма переписывающая (модифицирующая код). А функциональный стиль — это всего лишь синтакически-стилистическая особенность.
Вот тебе чисто функциональный пример исползования итераторов (точнее энумераторов, но это тоже самое, разница только в терминологии) в Шарпе:
int[] array = new int[] { 2, 4, 5, 8 };
int sum = 0;
Array.ForEach(array, delegate(int elem) { sum += elem; })
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Имхо все это неверно, т.к. все эти вещи, равно как и многие отличия шаблонов C++ от C# generics, позволяют использовать какие-то новые идиомы, и, соответственно, просто к "улучшению синтаксиса применения" не сводятся. По-моему, грань, отделяющая "улучшение синтаксиса" от "выполнения работы" как раз и лежит там, где добавление новых выразительных средств приводит к качественному изменению языка, давая пространство для новых идиом и стилей программирования.
И какие новые идиомы и т.п. даемт нам С++ по сравнению с Шарпом если таки выбросить аспект метапрограммирования?
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ты, похоже, пользуешься каким-то уж очень нетрадиционным определением метапрограммирования.
ПК>А функция find() в этих "обыкновенных" контейнерах Vector и List тоже "будет метапрограммированием"? Если нет, чем она отличается от итераторов? Если да, то я вообще не понимаю, где в твоей трактовке грань между generic программированием, и метапрограммированием.
ПК>Если мы уберем из контейнеров итераторы, то, по-видимому, придется добавить индексацию (operator []). Индексация тоже "будет метапрограммированием", или нет?
Кончай ловить его на словах. Примеры в студию, того что нельзя сделать на дженириках и при этом это не относится к метапрограммированию. Про эффетивность тоже заводить разговор не нужно.
Ты подверг сомнению утверждение "дженерики обладают теми же возможностями, что и шаблоны за исключением метапрограммирования". Так? Ну, вот и попытайся доказать неверность этого утвержения. А не борись со всеми мельницами в округе.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, McSeem2, Вы писали:
MS>Точно! Может скажу и не в кассу, но слово "метапрограммирование" во мне до сих пор вызывает какой-то ступор, почти как "контрреволюция" — совершенно не понятно, что под ним скрывается. С этой точки зрения термин "generic" — гораздо более удачен. Есть сильное подозрение, что он рассчитан на профанов типа меня, не понимающих слова "метапрограммирование"
В точку. К сожалению таких как ты очень много.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, McSeem2, Вы писали:
MS>На самом деле, все выпады дот-нетчиков в сторону C++ сводятся к одной простой фразе: MS>
MS>Если вы все такие умные, чего же вы строем не ходите?
MS> Без обид!
Ну, тешить себя недеждами можно сколько угодно. Вот только выпады идут не только от дотнетчиков. Да и странно, что многие люди не тупее тебя бросили этот самый С++ и с радуются от того что это сделали.
В общем, дежавю какое-то. Все те же выподы только с большим сарказмом С++ вместо С. То ли еще будет...
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, AndrewVK, Вы писали:
AVK>>То что ты не знаешь языков гибче С++ еще не значит что их не существует. Например OpenC++ по гибкости на порядок круче С++.
MS>Фактически, если я о них не знаю, это как раз и означает, что их нет.
Космические масштабы отдыхают...
MS> Это все делается на уровне доморощенного энтузиазма, так же, как мой AGG или R#. До стандартизации и промышленного применения — ох как далеко. Короче говоря, здесь я больше верю в дот-нет, чем в OpenC++.
Ну, хотя бы сошлись на том, что в С++ мы уже точно не верим.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> И какие новые идиомы и т.п. даемт нам С++ по сравнению с Шарпом если таки выбросить аспект метапрограммирования?
Чтобы не углубляться в очередной терминологический спор, сформулируем просто: в шаблонах C++ можно использовать все возможности языка C++, в C# generics все возможности языка C# использовать нельзя. Т.е. часть алгоритмов, которые можно на C# написать, обобщить до generics не получится. С шаблонами C++ таких проблем нет.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VladD2,
> Ты совершенно прав в том, что дженерики отличаются от шаблонов (с точки зрения взможностей) только тем, что они не позволяют заниматься метапрограммированием, и позволяют не нарушать компонентную модель (и другие рантаймные тахнологии).
У Андрея хоть аргументы какие-никакие были. А тебе достаточно повторять данное утверждение, вероятно, полагая, что от этого оно станет более верным, или аргументы все-таки последуют?
> Ошибка же ПК более глобальна. Для него "С++ — это Аллах, а шаблоны пророк его".
Я очень хорошо знаю о недостатках C++ и его шаблонов. Но точно так же я вижу, что C# generics лишены достоинств шаблонов. За исключением одного: уменьшения потребности в явных приведениях типов. В данном случае я склонен согласиться с Брюсом Эккелем: generics aren't.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
McSeem2,
> ПК> часть алгоритмов, которые можно на C# написать, обобщить до generics не получится. С шаблонами C++ таких проблем нет.
> Это просто разные по своей сущности вещи. Общего в них лишь использование угловых скобок.
+1
> Щас снова скажу крамолу (вах, боюс-боюс). > Шаблоны по своей сути — это макросы, какими бы умными "метапрограммированиями" их ни обзывали.
(Ну и гаразд же ты терминами крутить) собственно, в этом их сила. Как и макросы, шаблоны были призваны заменить собой copy-paste. В отличие от generics, они с этой задачей вполне в состоянии справиться. И как оказалось впоследствии, и еще с некоторыми, хотя уже далеко не с такой же элегантностью
> Генерики полностью свободны от недостатков шаблонов, поскольку принципиально runtime. Но ведь они и не дают ничего существенного. Как было убедительно показано, они — всего лишь автоматизация dynamic cast.
+1
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>VladD2,
>> Ты совершенно прав в том, что дженерики отличаются от шаблонов (с точки зрения взможностей) только тем, что они не позволяют заниматься метапрограммированием, и позволяют не нарушать компонентную модель (и другие рантаймные тахнологии).
ПК>У Андрея хоть аргументы какие-никакие были. А тебе достаточно повторять данное утверждение, вероятно, полагая, что от этого оно станет более верным, или аргументы все-таки последуют?
Забавный ты мужик. У самого вместо аргументов докапывание к отдельным ошибкам аппонента не имеющим отношения к делу. А от других сразу аргументов требуешь.
Давай-ка лучше ты сам поищешь доказательства своим утверждениям. Попытайся найти хотя бы один случай обобщенного программирования не реализуемый на дженериках но реализуемый на шаблонах. При этом этот случай не должен являться случаем метапрогараммирования. Этого будет достаточно чтобы доказать неверность утверждений. Случаи параметризации классов значениями тоже не берем, так как это уже случай приципиально не имеющий отношения к обобщенному программированию и кроме как для метапрограммирования особых приемуществ не дает (а вот понимание усложняет очень даже).
Сразу скажу, что итераторы идут лесом так как они легко реализуются на дженериках, да и без них. Более того уже реализованы, только называются энумераторами.
>> Ошибка же ПК более глобальна. Для него "С++ — это Аллах, а шаблоны пророк его".
ПК>Я очень хорошо знаю о недостатках C++ и его шаблонов. Но точно так же я вижу, что C# generics лишены достоинств шаблонов.
Или недостатоков. Это завист от того как смотреть. Ну, да тут о достоинствах или недостатках вроде никто не гворил. Предлагаю не преключать тему. Ты утверждаешь, что у Шаблонов есть еще какие-то качественные приемущества кроме возможности метапрограммирования на них. Вот и обоснуй свое утверждение.
ПК> За исключением одного: уменьшения потребности в явных приведениях типов.
О. Этот пассаж я уже слышал не раз. С некоторой долей цинизма можно сказать, что так оно и есть. Ведь по большому счету, что такое обобщенное программирование как не создание полиморфного кода не имеющего приведений типов? Вот только я привык называть это обощенным программированием.
ПК> В данном случае я склонен согласиться с Брюсом Эккелем: generics aren't.
Ты случаем не обратил внимания на две мелочи? Нет? Такие незаметнинькие...
1. Он говорит о Яве. А в яве дженерики реализованы с серьезными ограничениями.
2. Они забыл разобраться в дэенериках.
Я не буду говорить за яву. Вместо этого дам тебе пару намеков. В Шарпе есть две сущьности обеспечивающие полуную абстракцию и дающие дженерикам мощь (в области обобщенного программирования) не меньшую чем шаблонам. При этом избавляющие от недостатков присущих пакросоподобным шаблонам.
Что это? Дык дженерик-интерфейсы и дженерик-делегаты.
Мне вообще-то казалось, что сам факт того, что ты и сам додумался как их использовать должен был уберечь тебя от ссылки на стольк некомпетентные источники.
Все эти "зеро эдвантедж" и т.п. выглядят просто смешно. Ну, прям идиоты сделали никому не нужную вещь, а он один провидец все увидел.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Чтобы не углубляться в очередной терминологический спор,
Да, уж. Желательно. А то как-то это докапывание до разной ерунды надоедает.
ПК> сформулируем просто: в шаблонах C++ можно использовать все возможности языка C++, в C# generics все возможности языка C# использовать нельзя.
Да, Пашь, давать прямые форулировки чревато. Вот превое утверждение и сразу ошибка. То-то я гляжу ты все других на утверждения подбиваешь.
ПК> Т.е. часть алгоритмов, которые можно на C# написать, обобщить до generics не получится. С шаблонами C++ таких проблем нет.
В дженериках нельзя вызывать операторы и конструкторы с параметрами. Обе проблемы решаются с помощью дженерик-делегатов или дженерик-интерфейсаов.
В общем, приводи мне недженерик код на Шарпе и я тебе перепишу его на дженериках.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, Павел Кузнецов, Вы писали:
ПК>>Чтобы не углубляться в очередной терминологический спор, сформулируем просто: в шаблонах C++ можно использовать все возможности языка C++, в C# generics все возможности языка C# использовать нельзя. Т.е. часть алгоритмов, которые можно на C# написать, обобщить до generics не получится. С шаблонами C++ таких проблем нет.
MS>Это просто разные по своей сущности вещи. Общего в них лишь использование угловых скобок.
MS>Щас снова скажу крамолу (вах, боюс-боюс). MS>Шаблоны по своей сути — это макросы, какими бы умными "метапрограммированиями" их ни обзывали. Конечно, это не сишные define-макросы, они гораздо мощнее — хотя бы тем, что их можно нормально (иногда!) трассировать в отладчике. Но в этом-то и проблемы тоже — ужасающие сообщения об ошибках компиляции. Чего бы там ни говорили, но человек — не компилятор и "вкурить" сообщение длиной в килобайт — иногда повеситься можно. Кстати, это не просто так нельзя использовать что-то типа MS>
MS>Если такое разрешить, то на адекватном трассировании сразу можно ставить жирный крест — возвращаемся к базотладочным временам лог-файлов.
Вот до сюда согласен с каждым словом.
MS>Генерики полностью свободны от недостатков шаблонов, поскольку принципиально runtime. Но ведь они и не дают ничего существенного. Как было убедительно показано, они — всего лишь автоматизация dynamic cast. Типа просто надо было придумать некий "наш ответ Страуструпу — мы тоже умеем использовать угловые скобки"
А вот это, прости, эдакое лукавство. "Как было убедительно показано". Это кем и что было доказано? Уж не Брюсом Эккелем? Берусь доказать что он не долго разбирался с дженериками в дотнете.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Как и макросы, шаблоны были призваны заменить собой copy-paste.
Ну, то есть дженерики надо понимать copy-paste собой не заменяют?
ПК> В отличие от generics,
Точно... не заменяют. Ну, давай доказывай.
ПК>они с этой задачей вполне в состоянии справиться.
Ну, ну... Примеры в студию.
ПК> И как оказалось впоследствии, и еще с некоторыми, хотя уже далеко не с такой же элегантностью
Не, Пашь, оказалось, что их макросная суть настолько макросная, что нетрудно втиснуть в средство, казалось бы, предназначенное только для обобщенного программирования еще и кодогенерацию.
>> Генерики полностью свободны от недостатков шаблонов, поскольку принципиально runtime. Но ведь они и не дают ничего существенного. Как было убедительно показано, они — всего лишь автоматизация dynamic cast.
ПК>+1
Осталось только доказать провату своих слов.
А пока я вижу ничем не обоснованные утверждения.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Нельзя использовать все возможности языка (того же C# в данном случае).
Ой ли?
ПК> Например, использовать перегруженные операторы,
Перегруженные тут причем?
Операторы? Ну, это как сказать. Вот так напрямую может и нельзя. А если абстарагировать, то вполне можно. Вот, например, обобщенное (гы-гы) сумирование:
using System;
using System.Collections.Generic;
class Program
{
delegate T Adder<T>(T x, T y);
static T Sum<T>(Adder<T> adder, IEnumerable<T> list)
{
return Sum<T>(adder, list, default(T));
}
static T Sum<T>(Adder<T> adder, IEnumerable<T> list, T init)
{
T value = default(T);
foreach (T elem in list)
value = adder(value, elem);
return value;
}
// Реализация абстрактных операций для целых и временных
// отрезков. Для строк ничего писать не нужно, так как можно воспользоваться
// функцией string.Concat. Заметь! Статической. :)static int IntAdd(int x, int y) { return x + y; }
static TimeSpan TimeSpanAdd(TimeSpan x, TimeSpan y) { return x + y; }
static void Main()
{
// Сумируем целые.int intValue = Sum<int>(IntAdd, new int[] { 1, 3, 5, 7, 8, 9 });
Console.WriteLine("intValue is " + intValue);
// Сумируем временные промежутки.
TimeSpan timeSpanValue = Sum<TimeSpan>(
TimeSpanAdd,
new TimeSpan[]
{
new TimeSpan(10, 0, 0), new TimeSpan(10000),
new TimeSpan(1, 12, 10), new TimeSpan(20000)
});
Console.WriteLine("timeSpanValue is " + timeSpanValue);
// Сумируем строки. Кстати, функция уже есть, так что писать ее не нужно.string strValue = Sum<string>(
string.Concat,
new string[] { "the ", "power ", "of ", "generic ", "programing! :)" }
);
Console.WriteLine("strValue is " + strValue);
}
}
ПК> статические методы,
А сверху то я какие передаю? Или мне вызвать что ли нельзя? Дык и это можно.
ПК> конструкторы с аргументами.
Как если их тоже обощить? Ну, делаем делегат:
delegate T ClassMethod<T, X>(int i, string s, X x);
и вперед с песней.
ПК> Последнее ограничение, например, не позволяет сделать шаблон фабрики. Первое — даже простейший шаблон accumulate.
О как? А я сверху не то же самое сотварил? Нет?
Одна подсказка. Для фабрик классов в дотнете рулят грибы Сарумяна и танковые клинья в виде все тех же обобщенных интерфейсов и делегатов.
В общем, то что ты считашь недоработками или недостаткаи есть резултат отличной работы дизайнеров языка кторым удалось впихнуть в рамки простого языка концепцию обобщенного прграммирования. При этом они это сделали очень задорово! Они не пожертвовали компонентными свойствами языка (и фрэмворка). Решили массу проблем. И самое главноее, они умудрились оставить язык простым!
Если ребята из команд "CLR performance team" и Феникса как следует напрягуться и сделают достойный оптимизирующий прекомпилятор и джит, то мы получим бескомпромисную и чртовски удобную систему разработи.
Остается только метапрограммирование. Ну, что же... эту проблему я думаю тоже рано или поздно решат. Возможно ни без моей помощи.
А от плюсов мня все больше и больше ташнит. Когда-то это был мой любимый язык. Он даже стал круче с тех пор как я забил на него. Но писать на нем не тянет. А воспоминания о нем далеко не радужные.
Питоны и Руби по своему красивы и уж точно достойны внимания. Но то что код написанный на них будет стольк же надежен и производителен лично лично у меня вызвает слишком большие сомнения. Да и не нравятся мне, откровенно говоря, нетипизированные языки.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> Операторы? Ну, это как сказать. Вот так напрямую может и нельзя.
Именно о "напрямую" и идет речь.
> А если абстарагировать, то вполне можно. Вот, например, обобщенное (гы-гы) сумирование: >
> static int IntAdd(int x, int y) { return x + y; }
> static TimeSpan TimeSpanAdd(TimeSpan x, TimeSpan y) { return x + y; }
>
Теперь, пожалуйста, сделай generic вариант вот этих вот двух функций, чтоб не нужно было делать copy-paste для каждого нового типа. Что, не получается? То-то. Об этом и речь. Вот вариант в виде шаблона:
template<class T>
static T Add(T x, T y) { return x + y; }
> ПК> конструкторы с аргументами. > > Как если их тоже обощить? Ну, делаем делегат: >
> delegate T ClassMethod<T, X>(int i, string s, X x);
>
> и вперед с песней.
Ага, с песней. Для каждого типа.
> ПК> Последнее ограничение, например, не позволяет сделать шаблон фабрики. Первое — даже простейший шаблон accumulate. > > О как? А я сверху не то же самое сотварил? Нет?
Нет, ты сделал второй вариант. Чаще используется первый. Первый ты сделать на C# не сможешь из-за ограничений generics.
> В общем, то что ты считашь недоработками или недостаткаи есть резултат отличной работы дизайнеров языка кторым удалось впихнуть в рамки простого языка концепцию обобщенного прграммирования.
"Пока наши корабли бороздят просторы космоса". Может, оно и "результат отличной работы дизайнеров", но вот простую проблему избавления от copy-paste так и не решает...
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, VladD2, Вы писали:
ПК>> Как и макросы, шаблоны были призваны заменить собой copy-paste.
VD> Ну, то есть дженерики надо понимать copy-paste собой не заменяют?
VladD2,
> > ПК> сформулируем просто: в шаблонах C++ можно использовать все возможности языка C++, в C# generics все возможности языка C# использовать нельзя. > > Да, Пашь, давать прямые форулировки чревато. Вот превое утверждение и сразу ошибка. То-то я гляжу ты все других на утверждения подбиваешь.
Т.е. непосредственно в generics можно вызвать статическую функцию для объекта класса, заданного generic параметром, или можно непосредственно вызвать операторы + — / *, или можно создать такой объект непосредственно в generic функции, если конструктор объекта требует аргументов? Ну-ну...
> ПК> Т.е. часть алгоритмов, которые можно на C# написать, обобщить до generics не получится. С шаблонами C++ таких проблем нет. > > В дженериках нельзя вызывать операторы и конструкторы с параметрами. Обе проблемы решаются с помощью дженерик-делегатов или дженерик-интерфейсаов.
Ага, с помощью copy-paste. Спасибо, не надо.
> В общем, приводи мне недженерик код на Шарпе и я тебе перепишу его на дженериках.
VladD2,
> У самого вместо аргументов докапывание к отдельным ошибкам аппонента не имеющим отношения к делу.
Имеющим самое непосредственное: от определения того, что является метапрограммированием, а что нет, напрямую зависит верность изначального тезиса о том, что отличия generics C# от шаблонов C++ сводятся к поддержке метапрограммирования.
> Давай-ка лучше ты сам поищешь доказательства своим утверждениям. Попытайся найти хотя бы один случай обобщенного программирования не реализуемый на дженериках но реализуемый на шаблонах.
> Случаи параметризации классов значениями тоже не берем, так как это уже случай приципиально не имеющий отношения к обобщенному программированию и кроме как для метапрограммирования особых приемуществ не дает (а вот понимание усложняет очень даже).
Принципиально или непринципиально, но это еще одно ограничение на использование обобщенного программирования.
> ПК> В данном случае я склонен согласиться с Брюсом Эккелем: generics aren't. > > Ты случаем не обратил внимания на две мелочи? Нет? Такие незаметнинькие... > 1. Он говорит о Яве. А в яве дженерики реализованы с серьезными ограничениями.
Читай внимательнее. Он говорит и о C#:
But in Java (and apparently C#), you can't seem to say "any type."
C# also doesn't support latent typing, and although it has a better generics model than Java (since they went ahead and changed the underlying IL so that, for example, a static field in a class will be different between class and class). So if you want latent typing you'll have to use C++ or D (or Python, Smalltalk, Ruby, etc.).
> 2. Они забыл разобраться в дэенериках.
Да уж, конечно, кроме тебя никто эту сложную вещь не понял.
> Мне вообще-то казалось, что сам факт того, что ты и сам додумался как их использовать должен был уберечь тебя от ссылки на стольк некомпетентные источники.
В результате своих экспериментов я и пришел к более-менее тем же выводам, что и Брюс Эккель.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Т.е. непосредственно в generics можно вызвать статическую функцию для объекта класса, заданного generic параметром, или можно непосредственно вызвать операторы + — / *, или можно создать такой объект непосредственно в generic функции, если конструктор объекта требует аргументов? Ну-ну...
А что есть разница между посредственной или непосредственной? Факт в том, что можно. И довольно просто.
А вот классификация дженериков как средство борьбы с приведением типов в лучшем случае заблуждение.
>> В дженериках нельзя вызывать операторы и конструкторы с параметрами. Обе проблемы решаются с помощью дженерик-делегатов или дженерик-интерфейсаов.
ПК>Ага, с помощью copy-paste. Спасибо, не надо.
Где? У тебя уже копипэст просто мерешится везде. Копипэст скорее будет вызван соображениями производительности нежели проблемами с дженериками.
В общем, ты опять подменяешь тему чтобы уйти от необходимости признать очевидное.
>> В общем, приводи мне недженерик код на Шарпе и я тебе перепишу его на дженериках.
ПК>http://rsdn.ru/forum/?mid=1015985
VladD2,
> ПК> Т.е. непосредственно в generics можно вызвать статическую функцию для объекта класса, заданного generic параметром, или можно непосредственно вызвать операторы + — / *, или можно создать такой объект непосредственно в generic функции, если конструктор объекта требует аргументов? Ну-ну... > > А что есть разница между посредственной или непосредственной?
Да, естественно. Опосредованно шаблоны можно тоже из DLL экспортировать.
> А вот классификация дженериков как средство борьбы с приведением типов в лучшем случае заблуждение.
Пока так и не было продемонстрировано, что позволяют сделать generics, чего нельзя сделать обычным классом, если не принимать во внимание необходимость приведений типов во втором случае.
>>> В общем, приводи мне недженерик код на Шарпе и я тебе перепишу его на дженериках. > > ПК>http://rsdn.ru/forum/?mid=1015985
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Имеющим самое непосредственное: от определения того, что является метапрограммированием, а что нет, напрямую зависит верность изначального тезиса о том, что отличия generics C# от шаблонов C++ сводятся к поддержке метапрограммирования.
Нет уж. Не имеющих. Ты утверждаешь:
1. Дженерики всего лишь средство избавления от приведений типов.
2. Дженерики неполноценное средство обобщенного программирования.
То что итераторы не имеют отношения к метапрограммированию никак не касается этих утверждений. Так что уципился ты за них только потму-что больше не за что. И выглядит это очень некрасиво.
>> Давай-ка лучше ты сам поищешь доказательства своим утверждениям. Попытайся найти хотя бы один случай обобщенного программирования не реализуемый на дженериках но реализуемый на шаблонах.
ПК>http://rsdn.ru/forum/?mid=1015985
Зачем столько раз давать ссылку на то где тебе уже дали ответ? Мой код не решает проблемы? Он не обобщен?
Ну, вот и подищи что-нибудь по новее. И не нужно давать ссылку на мое же сообщение. Это уже не смешно.
>> Случаи параметризации классов значениями тоже не берем, так как это уже случай приципиально не имеющий отношения к обобщенному программированию и кроме как для метапрограммирования особых приемуществ не дает (а вот понимание усложняет очень даже).
ПК>Принципиально или непринципиально, но это еще одно ограничение на использование обобщенного программирования.
Это вообще не относится к обобщенному программированию. Параметризация константами (если о ней речь) может быть полезна только при генерации кода (метапрограммировании).
>> 1. Он говорит о Яве. А в яве дженерики реализованы с серьезными ограничениями.
ПК>Читай внимательнее. Он говорит и о C#:
Я читаю внимательно. Упоминаний Шарпа в статье два. Оба в суе и бездоказательно.
ПК>
But in Java (and apparently C#), you can't seem to say "any type."
apparently нареч.
1) очевидно, несомненно Syn: evidently
2) вероятно, видимо, по-видимому, предположительно Syn: to all appearance
Как ты думашь, автор применил слово в первом или втором значении? Если в первом, но от воинствующий ламер и слушать его просто глупо. Если во вотором, то возможно этим он хотел сказать, что просто не разбирался в дотнете?
Мне кажется я дал доволнь много примеров, что бы понять, что все слова о бессмысленности или ущербности дженериков просто бред сивой кобылы.
ПК>
C# also doesn't support latent typing, and although it has a better generics model than Java (since they went ahead and changed the underlying IL so that, for example, a static field in a class will be different between class and class). So if you want latent typing you'll have to use C++ or D (or Python, Smalltalk, Ruby, etc.).
И что ты тут усмотрел? То что в Шарпе дженерики лучше? Ды я и не спорю. Или то что макросы или интерпретация лучше чем компилируемые компоненты? Да арзные подходы. Но обоснования, что один хуже, а другой лучше я что-то не увидел.
>> 2. Они забыл разобраться в дэенериках.
ПК>Да уж, конечно, кроме тебя никто эту сложную вещь не понял.
Зачем же передергивать. Вешь не особо сложная. Вот только наблюдается явная тенденция к тому, что некоторые привыкшие к одному подходу воспринимают в штыки все новое и даже не пытаются вникнуть и оценить. Товаришь явно несет чушь. Стало быть или неразобрался, или развивает целенаправленную демагогию. Я склоняюсь к первому.
>> Мне вообще-то казалось, что сам факт того, что ты и сам додумался как их использовать должен был уберечь тебя от ссылки на стольк некомпетентные источники.
ПК>В результате своих экспериментов я и пришел к более-менее тем же выводам, что и Брюс Эккель.
Странно. А код получился хотя и кривой, но более мнее обобщенный. Не уж то избавление от привдения типов дает стольк мощьный эффект? А может тогда ну, их эти слова про бобщенное программирование? Может все что нужно это как раз избавление от приведения типов.
В общем, твои ужимки уже столь откровенны, что разговор становится не интересным. Ты начал называть черно белым и отрицать очевидные вещи. На это думаю, нужно и завершить. Люди с головой все поймут, а ты все равно не признаешь своих заблуждений.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Да, естественно. Опосредованно шаблоны можно тоже из DLL экспортировать.
Да ну? А можно пример посмотреть?
ПК>Пока так и не было продемонстрировано, что позволяют сделать generics, чего нельзя сделать обычным классом, если не принимать во внимание необходимость приведений типов во втором случае.
Дык написать обобщенный алгоритм или контейнер. Или ты о том, что и обобщенное программирование и динамический полиморфизм суть проявления полиморфизма и с филосовской точки зрения обладают равными возможностями? Ну, так тогда и шаблоны не более чем средство борьбы с приведениями типов. Я на С++ писал еше когда компиляторы не знали что такое шаблоны. Вроде возможностей хватало. Не так удобно конечно, но жить можно. И как не странно копипэста тоже практически небыло. Да и на С. Не поверишь, но и на нем можно без копипэстов...
В общем, это несерьезно. Очевидно, что дженерики — это полноценное средство обобщенного программирования. Примеров которые невозможно реализовать ты так и не привел. Признаваться что не прав тоже не хочешь.
ПК>Ошибся. Подразумевалось: http://rsdn.ru/Forum/Message.aspx?mid=1016014&only=1
Вот это уже пример метапрограммирования. На макросах, кстати, делается еще проще. Тут уже на уровен типов ничего не сделашь. Хотя твое случай решается еще проще. Массив байтов и вперед. А уж абстрагироваться через методы.
MS>Производительность при динамической параметризации (переменными) сразу падает в несколько раз — на любом языке, хоть на ассемблере.
Дык, не ты ли говорил, что если что мы по бырому генератор кода сварганим? Ну, и вообще-то умный джит в данном случае мог бы обеспечить оптимизацию. Все же инварианты можно было бы вывести за пределы циклов.
MS> Тут уж ничего не поделаешь. А в C#-генериках параметризовать константами нельзя.
На то они и дженерики. Иначе пршлось бы код генерировать. Тут уже мсил был бы разный.
MS> Единственный выход для сохранения производительности — copy/paste. В минимальном варианте получаем: MS>2 варианта ValueT — uint8, uint16, MS>4 варианта Order MS>3 варианта BaseShift для случая uint16 (12, 14, 16)
MS>Итого 2*4 + 2*4*3 = 32 варианта одного и того же кода в виде банального Copy/Paste.
Сдается мне, что все несколько проще. Это ты своих тараканов размножаешь.
MS>На голом Си это можно хотя-бы дефайнами сделать (тяжело, некрасиво, но можно). Ни на Java, ни на C#, ни на Фортнане задача не решается в принципе.
О как. А значит препроцессор у нас религия для Явы или Шарпа запрещает использовать?
Возми тот же VC у него есть опция командной строки раскрывающая препроцессор. И будет тебе препроцессор для шарпа. Ну, и геморрой соотвествующий.
А по уму твоя проблема решается кодогенератором. Качаешь R# или КодСмит и через пять минут решение твоей неразрешимой проблемы. Причем чистое, красивое, и легко отлаживаемое.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Нужно ехать: нужно, чтобы клиент не копипэйстил x + y в своем коде, а это было сделано один раз в шаблоне.
Ну, себя ты уже явно убедил. Столь ужасный копипэст действительно является серьезным основанием чтобы возиться с полумакросными технолгиями, пялиться в найрен не нужные навороты и читать трехметровые сообщения об ошибках.
>> ПК>Теперь, пожалуйста, сделай generic вариант вот этих вот двух функций, чтоб не нужно было делать copy-paste для каждого нового типа. Что, не получается? То-то. Об этом и речь. Вот вариант в виде шаблона: >> ПК>
>> ПК>template<class T>
>> ПК>static T Add(T x, T y) { return x + y; }
>> ПК>
>> А у тебя получится?
ПК>С generics? Нет, и у меня не получится. Поэтому и говорю, что они этого не позволяют.
Зачем? С любым классом. Чтобы у него вот раз и сам по себе появился оператор сложения.
ПК>Не годится. Класс уже написан, не нами. Например, это int.
А если у класса вообще нет оператора сложения? Ой прийдется все же тебе копипэстить. И как ты через себя перешагнешь?
>> Ну, да ради искуства... напишу тебе универсальную функцию : >>
>> static Adder<T> GetAdditionOperator<T>()
>> {
>> return (Adder<T>)Delegate.CreateDelegate(
>> typeof(Adder<T>), typeof(T), "op_Addition");
>> }
>> ...
>> TimeSpan timeSpanValue = Accumulate<TimeSpan>(
>> GetAdditionOperator<TimeSpan>(),
>> new TimeSpan[]
>> {
>> new TimeSpan(10, 0, 0), new TimeSpan(10000),
>> new TimeSpan(1, 12, 10), new TimeSpan(20000)
>> });
>> Console.WriteLine("timeSpanValue is " + timeSpanValue);
>>
>> На жлабэйские операторы и вовсе доступны в виде методов.
ПК>Ерунда. Просто место copy-paste изменилось. Где само x + y, там и copy-paste.
А где "x + y"? Ты код то прочел? Ну, давай с коментариями, чтобы для танкистов:
// Процедура универсального получения делегата метода сложения.
// Если у типа реализован оператор сложения, то он обязательно
// содержит статический метод op_Addition.
// Таким образом мы создаем делегат для этого метода/типа.static Adder<T> GetAdditionOperator<T>()
{
return (Adder<T>)Delegate.CreateDelegate(
typeof(Adder<T>), typeof(T), "op_Addition");
}
...
TimeSpan timeSpanValue = Accumulate<TimeSpan>(
// Применяем универсальный метод. Вместо TimeSpan
// можно подставить любой тип реализующих оператор сложения.
GetAdditionOperator<TimeSpan>(),
new TimeSpan[]
{
new TimeSpan(10, 0, 0), new TimeSpan(10000),
new TimeSpan(1, 12, 10), new TimeSpan(20000)
});
Console.WriteLine("timeSpanValue is " + timeSpanValue);
Так яснее?
ПК>Это означает, что клиенты моего "generic" класса будут в своем коде делать copy-paste для каждого нового типа, с которым они мой "generic" класс захотят использовать. Или, если "по месту", то не для каждого типа, а в месте каждого вызова.
Это означет, что тебе болше придумать нечего. А ничего что ты операторы постоянно копипэстиш? Не думл на счет написания шаблона заменяющего их?
Не неси откровенню чушь. Если тип встречается один раз, то сделашь анонимный метод. Если он встречается часто, то опишешь метод. Если уж ты такой эстет, то возмешь метод описанный выше.
>> Да и это ты уж совсем из пальца проблемы высасывашь. На практике такие изыки встречаются крайне редко. А фабрики классов обычно делаются на базе активатора, так как в отличии от плюсов все компоненты и любой класс можно создать динамически. С точки зрения фабрики классов намного выгоднее прописать все что нужно в файле настроек и создавать классы по этим описаниям.
ПК>Ага. Например, создание таким макаром результата функции получения ряда матрицы... Представляю
Ряда? Хотя пофигу. Почему бы нет?
>> Ты еще не забыл, что я тут в основном против твоего заялления о бесполезности дженериков спорю
?
ПК>Не о бесполезности, а об отсутствии у них достоинств шаблонов.
Недостатков ты хотел скзать? Да пойими ты. Они просто другие. Да, операторы нужно абстрагировать. Но это не та проблема. За то прозрачная передача абстракции через любые границы. Можно даже тип на диск записать и потом считать. Компонентная архитектура при минимуме неудобств. Плсы идут обижаться на КОМ.
ПК>Я отлично понимаю, почему именно так происходит. Тем не менее copy-paste остается. И чем сложнее будет generic функция (чем больше ей будет нужно операторов), тем больше этого дублирования будет.
Блин, ты про абстракцию что-нибудь слышал? Дженерик-делегаты и дженерик-интерфейсы — это такая же абстракция как указатели на функцию или простые интерфейсы. Реализация абстракции тоже вольна состоять из обращения к абстракции. Про декомпозицию тоже надеюсь слышал?
Если правильно проектировать, то нет никакого дублирования кода в при использовании дженериков. Это ты тут из пальца проблемы высасывашь, чтобы не признавать своей не правоты.
ПК>Это потому что ты математику на generics писать не пытался.
А зачем? Она в System.Math валяется. И без всяких дженериков в лучшем виде обходится. Абстрагировать даблы — это уже маразм. В общем, мне лично хватает и System.Math. Появятся серьезные оптимизаторы и можно будет все на дженериках переписать не боясь потерять скорость. Вот только зачем?
>> Вот к С++ претензий хоть отбавляй. Попробуй ради хохмы передать ссылку на метод по сети. Получишь гору фрэймворков вроде КОМ или КОРБА и море геморроя.
ПК>Ерунда. Для этого, если будет нужно, можно и тот же .Net использовать. .Net — платформа, с тем же успехом доступная и из C++.
Не. На МС++ ты передашь тот же дерегат. Максиумут дженерик. А все твои бусты пойдут лесом.
Хотя прием красивый. В следующий раз буду давить на то, что на МСИЛ-ле можно черта лысого сварганить.
ПК>Предлагаю продемонстрировать пример на generics, который нельзя сделать обычным классом, если закрыть глаза на приведение типов.
А на шаблонах без метапрограммирование такое возможно? Что до демагогии спускаться то? Обобщенное программирование и подразумевает статически типизированное программировние на бзе абстрактных типов.
А уж генерация кода не связанная с типами или подключение релизаций — это просто еще одна схожая область автоматизации. В том, что плюсы позволяют делать многое за счет метапрограммных свойств (макросных можно сказать) никто и не спорит. Но без этого и шаблоны делают тоже самое. Да и предназначились они для того же.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Это по какому определению? По общепринятому — самое обычное обобщенное программирование, т.к. можно скопипэйстить для каждого из использующихся типов и значений Shift в неизменном виде. Т.е. классический параметрический полиморфизм.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VladD2,
> ПК> Нужно ехать: нужно, чтобы клиент не копипэйстил x + y в своем коде, а это было сделано один раз в шаблоне.
> Ну, себя ты уже явно убедил. Столь ужасный копипэст действительно является серьезным основанием чтобы возиться с полумакросными технолгиями, пялиться в найрен не нужные навороты и читать трехметровые сообщения об ошибках.
Это ж только пример. При попытке использования generics, например, для написания обобщенных матриц и векторов (в смысле линейной алгебры) ушьешься передавать туда делегаты. Будет самый настоящий copy-paste на стороне клиента.
Я все еще жду примера, где generics дают что-нибудь новое по сравнению с обычным классом, если закрыть глаза на приведение типов.
> А где "x + y"? Ты код то прочел? Ну, давай с коментариями, чтобы для танкистов: >
> // Процедура универсального получения делегата метода сложения.
> // Если у типа реализован оператор сложения, то он обязательно
> // содержит статический метод op_Addition.
> // Таким образом мы создаем делегат для этого метода/типа.
> static Adder<T> GetAdditionOperator<T>()
> {
> return (Adder<T>)Delegate.CreateDelegate(
> typeof(Adder<T>), typeof(T), "op_Addition");
> }
> ...
>
> Так яснее?
Да, так яснее. Это же можно сделать и без generics. Они здесь ничего нового по сравнению с обычными классами не дают.
> ПК>Это означает, что клиенты моего "generic" класса будут в своем коде делать copy-paste для каждого нового типа, с которым они мой "generic" класс захотят использовать. Или, если "по месту", то не для каждого типа, а в месте каждого вызова. > > Это означет, что тебе болше придумать нечего. А ничего что ты операторы постоянно копипэстиш? Не думл на счет написания шаблона заменяющего их?
Уже написано. <boost/operators.hpp>
> Не неси откровенню чушь.
Чего и вам желаю.
> А на шаблонах без метапрограммирование такое возможно? Что до демагогии спускаться то? Обобщенное программирование и подразумевает статически типизированное программировние на бзе абстрактных типов.
О, уже ближе. Теперь вернемся к примеру выше, и ответим на вопрос: является ли конструкция ниже примером "статически типизированного программирования":
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Это ж только пример. При попытке использования generics, например, для написания обобщенных матриц и векторов (в смысле линейной алгебры) ушьешься передавать туда делегаты. Будет самый настоящий copy-paste на стороне клиента.
Не уешся. На каждый тип нужно ровно один делегат. И передавать его не нужно. Положи ссылку в поле и используй. А если методов много, то заведи дженерик-интерфейс с ними. Реализация такого чуда — это пара пальцев об асфальт. Студия 90% работы слелает... За-то все четко специфицировано и явно.
ПК>Я все еще жду примера, где generics дают что-нибудь новое по сравнению с обычным классом, если закрыть глаза на приведение типов.
Что нового можно найти после появления структурного программирования? Если я чего-то не понимаю, то держни... покажи класс. Сделай на шаблонах это новое, но без метапрограммирования, плиз.
ПК>Да, так яснее. Это же можно сделать и без generics. Они здесь ничего нового по сравнению с обычными классами не дают.
Не, ну если все типы в object-ах, и постоянный боксинг-анбоксинг, да языком Шарп или Васик, то конечно. Ну, и если память и скорость невозна. Пишут же люди на скриптах? Но тут кто-то расскзаывал о типобезопасности, производительности и т.п. Это не ты был?
Мы вообще о чем? Ты как-то забавно выкручивашся. Что ты понимашь под обобщенным программированием? И какою качественную разницу ты видишь между дженериками и шаблонами?
ПК>Уже написано. <boost/operators.hpp>
Значит операторы уже мовитон? Однако. А почем у вас огурцы? (с)
ПК>О, уже ближе.
К чему?
ПК> Теперь вернемся к примеру выше, и ответим на вопрос: является ли конструкция ниже примером "статически типизированного программирования": ПК>
VladD2,
> ПК>Имеющим самое непосредственное: от определения того, что является метапрограммированием, а что нет, напрямую зависит верность изначального тезиса о том, что отличия generics C# от шаблонов C++ сводятся к поддержке метапрограммирования.
> Нет уж. Не имеющих. Ты утверждаешь: <...>
исходная мысль была о том, что большинство отличий в возможностях шаблонов имеют практическое значение при метапрограммировании, а не при дженерик-программировании
К этому тезису определение того, что же такое метапрограммирование, имеет самое наинепосредственнейшее отношение.
> То что итераторы не имеют отношения к метапрограммированию никак не касается этих утверждений. Так что уципился ты за них только потму-что больше не за что. И выглядит это очень некрасиво.
Речь об итераторах зашла до того, как я в этой ветке дал ссылку на Брюса Эккеля. Не путай все в одну кучу.
> Я читаю внимательно. Упоминаний Шарпа в статье два. Оба в суе и бездоказательно.
Опровергни.
> ПК>
But in Java (and apparently C#), you can't seem to say "any type."
> >
apparently нареч. <...> Как ты думашь, автор применил слово в первом или втором значении?
Абсолютно все равно, что означает "apparently". К C# все его рассуждения о Java применимы в полной степени со сделанными им оговорками о поддержке на уровне IL. В C# ты тоже, как и в Java, лимитирован интерфейсами. Подробнее см. в следующей статье, на которую, кстати, была ссылка из первой.
> ПК>[q]C# also doesn't support latent typing, and although it has a better generics model than Java (since they went ahead and changed the underlying IL so that, for example, a static field in a class will be different between class and class). So if you want latent typing you'll have to use C++ or D (or Python, Smalltalk, Ruby, etc.).
> > И что ты тут усмотрел? То что в Шарпе дженерики лучше?
Я выделил.
> наблюдается явная тенденция к тому, что некоторые привыкшие к одному подходу воспринимают в штыки все новое и даже не пытаются вникнуть и оценить. Товаришь явно несет чушь.
Или же ты не можешь/не хочешь понять, о чем идет речь.
> ПК>В результате своих экспериментов я и пришел к более-менее тем же выводам, что и Брюс Эккель.
> Странно. А код получился хотя и кривой, но более мнее обобщенный.
Скорее менее, из-за мест, где приходится делать copy-paste.
> В общем, твои ужимки <...>
Помнишь фильм "Кукушка"? Я скоро буду вынужден обращаться к тебе так же, как к главному герою того фильма, если ты не прекратишь хамить.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Это по какому определению? По общепринятому — самое обычное обобщенное программирование, т.к. можно скопипэйстить для каждого из использующихся типов и значений Shift в неизменном виде. Т.е. классический параметрический полиморфизм.
Нет, батенька. Тут и параметризация константами, и изменение структуры кода при изменении параметра типа. Натуральная кодогенерация. И потому легко решается с помощью макросов и кодогенераторов.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>На уровне возможностей generics? Пишешь обычный класс + шаблон-обвязку, приводящую аргументы и результаты функций. Класс экспортируется, шаблон включается обычным #include. Все, справился.
Ну, тоесть нельзя? Шаблон инклюдами... дальше уже можно не продолжать. Если хоть один метод с параметром типа скомпилирован, то новых специализаций уже не породить.
ПК>В чем, кроме отсутствия необходимости в приведениях типов, проявляется его обобщенность в случае generics?
В отсуствии необходимости применения боксинга, наследования, виртуальных методов. В применимости к вэлью-типам. В общем, во всем в том, что касается и шаблонов. В итоге статическая типобезопастность и повешение скорости.
А можно узнать что нового привносят в данном разрезе шаблоны?
ПК>Разными. Параметрический полиморфизм (aka основной инструмент обобщенного программирования) позволяет писать код идентичным образом для разных типов. Generics ограничивают множество конструкций до тех же, что доступны в "обычных", не generic, классах.
Чушь какая. Все что ты пишашь на шаблонах можно написать и в с использованием динамического полиморфизма и приведений типов. Параметризация типов у дженериков и шаблонов одинаковая. Разница только в том, что дженерики имет ораничение на интерфес, а шаблоны просто являются макроподстановками и следовательно ставят жирный крест на компонетах и рантайме.
ПК>Еще раз: конкретно, какие возможности доступны в generics, которые нельзя получить "обычными" классами, если не учитывать приведения типов?
Какое фамство? Ты уже часа 4 откровенно называшь белое черным и пыташся найти какие-то зацпки для обоснования этого. Мне это уже порядком надоело.
>> Я алгоритм реализовал? Он обобщенный? Что еще? Код на Камеа не компилируется?
ПК>"Алгоритм" в данном случае сводится x + y.
Нет, алгоритм своидится к сумированию списка. И пользуется абстрактной операцией тип которой определяется параметром типа.
ПК> Эту часть ты так в generics и не включил.
Дык эта часть не абстактна. В абстрактном коде все пучком. А это реализация частностей. Была бы в интерйейсе класса операция описана в виде метода и этого абстрагирования не потребовалось бы.
Шаблоны же как форменный макрос плют на неопределеность типов и все ОК. Вот только в шаблоне можно совсем невероятную чушь написать, а потом при появлении нового типа охренивать с простыми сообщений об ошибках.
ПК> Точнее, один вариант был, но основанный на "обычных", не generic средствах.
Так. Я алгоритм реализовал? Он обобщенный? Что еще? Если ответить не можешь, то одью.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
исходная мысль была о том, что большинство отличий в возможностях шаблонов имеют практическое значение при метапрограммировании, а не при дженерик-программировании
ПК>К этому тезису определение того, что же такое метапрограммирование, имеет самое наинепосредственнейшее отношение.
Вот порядок у этой кучи сообщений отследить трудно. Но трюк с итераторами был очень некрасив.
>> Я читаю внимательно. Упоминаний Шарпа в статье два. Оба в суе и бездоказательно.
ПК>Опровергни.
У него доказательств нет, а я должен опровергать? Хотя там и поровергать нечего.
>> ПК>
But in Java (and apparently C#), you can't seem to say "any type."
>> >>
apparently нареч. <...> Как ты думашь, автор применил слово в первом или втором значении?
ПК>Абсолютно все равно, что означает "apparently". К C# все его рассуждения о Java применимы в полной степени со сделанными им оговорками о поддержке на уровне IL.
Так к сведению... Разница между дженериками явы и шарпа в том, что дженерики шарпа умеют работать с вэльютипами. При этом получается эффективный код. Ява же вообще не поддерживает вэльютипы в качесвте параметров шаблонов. Вместо этого в нее введен автобоксинг и внешне код выглядит как будто он работает с вэлью-типами. Но на самом деле в коде идут настаящие операции боксинга/анбоксинга (что можно расценить как автоматическое приведение типов).
Если в шарпе в некий дженерик-метод передать вэлью-тип, то он убдет обработан именно как вэлью-тип. По всем правилам и с должносй скоростью. В Яве же он будет ссылочным типом с вытикающей семантикой и скоростью.
Далее в яве нет делегатов и в яве всегда существует только одна физическая раелизация дженерик-ласса. В Шарпе же если дженерик получает в качестве типа вэлью-тип, то создается отдельная специализация. Т.е. по сути получаетя поведение похожее на поведение шабонов С++.
ПК> В C# ты тоже, как и в Java, лимитирован интерфейсами. Подробнее см. в следующей статье, на которую, кстати, была ссылка из первой.
Спасибо, но сдается мне эта тема мне знакома несколько лучше чем тебе, и скорее всего чем ему.
>> ПК>[q]C# also doesn't support latent typing, and although it has a better generics model than Java (since they went ahead and changed the underlying IL so that, for example, a static field in a class will be different between class and class). So if you want latent typing you'll have to use C++ or D (or Python, Smalltalk, Ruby, etc.).
>> >> И что ты тут усмотрел? То что в Шарпе дженерики лучше?
ПК>Или же ты не можешь/не хочешь понять, о чем идет речь.
Ну, обясни. Или может ты пыташся понять, то чего нет?
ПК>Скорее менее, из-за мест, где приходится делать copy-paste.
От от неопытности. Все же подходы с плюсов не катят.
>> В общем, твои ужимки <...>
ПК>Помнишь фильм "Кукушка"? Я скоро буду вынужден обращаться к тебе так же, как к главному герою того фильма, если ты не прекратишь хамить.
Я не хамлю. В вижу попытки назвать белое черным, и мне это не нравится.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
исходная мысль была о том, что большинство отличий в возможностях шаблонов имеют практическое значение при метапрограммировании, а не при дженерик-программировании
Как, исходя из этого определения возможность использования операторов, вызова статических функций, создания объектов, параметризации целыми, явная и частичная специализация и т.п. относятся к метапрограммированию?
> ПК>Речь об итераторах зашла до того, как я в этой ветке дал ссылку на Брюса Эккеля. Не путай все в одну кучу. > > Вот порядок у этой кучи сообщений отследить трудно. Но трюк с итераторами был очень некрасив.
Дык, не надо приводить такие примеры/аргументы.
> ПК>Абсолютно все равно, что означает "apparently". К C# все его рассуждения о Java применимы в полной степени со сделанными им оговорками о поддержке на уровне IL.
> Так к сведению... Разница между дженериками явы и шарпа в том, что дженерики шарпа умеют работать с вэльютипами. При этом получается эффективный код. Ява же вообще не поддерживает вэльютипы в качесвте параметров шаблонов. Вместо этого в нее введен автобоксинг и внешне код выглядит как будто он работает с вэлью-типами. Но на самом деле в коде идут настаящие операции боксинга/анбоксинга (что можно расценить как автоматическое приведение типов).
"Но в песне ты не понял, увы, ничего". Эффективность в данном случае абсолютно побоку.
> ПК> В C# ты тоже, как и в Java, лимитирован интерфейсами. Подробнее см. в следующей статье, на которую, кстати, была ссылка из первой.
> Спасибо, но сдается мне эта тема мне знакома несколько лучше чем тебе, и скорее всего чем ему.
О какие пошли аргументы! Можно использовать мощные контр-аргументы: You have no clue. Absolutely. Перевожу: "Ты не рубишь. Совсем". Или еще вариант: "Нет, он/я/кто угодно лучше, чем ты шарит в этом"... В общем, лучше бы ты по существу говорил, если есть что, чем хвастаться.
> ПК>Скорее менее, из-за мест, где приходится делать copy-paste. > > От от неопытности. Все же подходы с плюсов не катят.
Так, куда мне сирому, если даже ты, опытный, не смог от copy-paste в такой простой вещи как x + y избавиться...
>>> В общем, твои ужимки <...> > > ПК>Помнишь фильм "Кукушка"? Я скоро буду вынужден обращаться к тебе так же, как к главному герою того фильма, если ты не прекратишь хамить. > > Я не хамлю. В вижу попытки назвать белое черным, и мне это не нравится.
Я могу адресовать то же самое и тебе. Просто у нас, как это часто бывает, очень различные взгляды на то, что есть черное, а что есть белое.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>На каждую используемую операцию каждого используемого типа — по делегату.
Если их более одной используй дженерик-интерфейс.
ПК>Ага. Не работает. Методы такие: +, -, *, / и т.п., т.к. generic алгоритм должен работать и со встроенными типами.
Опять же интерейс тебе поможет. Кто скзал, что его нужно реализовывать в типе? Сделай хэлпер. Ты же в С++ передаешь через параметр разные Аллокаторы и т.п. Ну, вот и тут. Творишь нечто вроде:
interface INumberOperations<T>
{
T Add(T x, T y);
T Sub(T x, T y);
T Mul(T x, T y);
T Div(T x, T y);
T Ect(T x, T y);
}
Далее для каждого своего типа заводишь по классу NumberOperations<ЭтотСамыйТип> и реализуешь эти операции в нем.
Ну, а во всех классах алгоритмов и т.п. хранишь ссылку на INumberOperations<T>.
Трудозатраты почти нулевые. Интерфейс чистый. Возможно динамически менять объект операций.
ПК>Предлагаемая тобой автоматизация дублирования кода обобщенным программированием не является.
Да нет тикакого дублирования. Весь коди или спецефичен или его с гулькин хнер. Просто тебе очень хочется, увидеть проблему там где ее нет.
>> Что нового можно найти после появления структурного программирования? Если я чего-то не понимаю, то держни... покажи класс. Сделай на шаблонах это новое, но без метапрограммирования, плиз.
ПК>Любой пример параметрического полиморфизма. Например: ПК>
ПК>template<class T>
ПК>Vector3<T> operator *( Vector3<T> const& v, T const& s )
ПК>{
ПК> return Vector3<T>( v1.x * s, v1.y * s, v1.z * s );
ПК>}
ПК>
ПК>Будет работать для любых скаляров T, начиная от int, float и заканчивая MyBigInt, MyRational, MyDecimal и т.п. В пример включен подразумеваемый шаблон Vector3<T> и т.п.
1 в 1 можно сделать на шарпе. Только вместо операций будут методы или объект-хэлпер. Разницы никакой.
ПК>С точки зрения типобезопасности (кроме избавления от приведений типов, о чем мы уже упоминали) generics ничего не дают по сравнению с интерфейсами.
Не, ну так самую млосьть они все же дают, если уж смотреть "с точки зрения типобезопасности". Они дают ту самую статическую проверку типов при отсуствии дублирования кода. Если ты еще что-то знаешь о типобезопасности, то поведай. Может я чего в этой жизни пропустил?
ПК> Производительность у generics тоже не блещет.
. Там забавный график есть. К сведенью, пункт "Array (CLR)" — это версия (гы-гы) оптимизированная на С++ с использованием шаблонов. Так вот убокие дженерики несколько быстрее. А вот небоскребы рядом — это как раз полиморфные решения. Боксинг из них самое дешевое (опять же гы-гы).
А еще могу вспомнить С-шный qsort который сливал моим тестам на шаблонах в разы. Так что ненада. А будет человеческий оптимизатор, так вообще разницы с VC не будет. Ну, а разные БЦЦ шарп и сейчас порой рвет.
ПК> Впрочем, отсутствие необходимости в boxing/unboxing можно тоже добавить, но это уже речь об оптимизации, а не о возможностях.
А о чем еще можно говорить если речь зашла о скорости кода? Или опять возвращаемся про никие мифическип архитектурные недостаткои дотнета или Шарпа?
>> Мы вообще о чем? Ты как-то забавно выкручивашся. Что ты понимашь под обобщенным программированием?
ПК>В первую очередь — использование параметрического полиморфизма.
И его в дотнете нет? О как?! Т.е. запрет на пямое использование операторов уже смертный приговор. То-то я в своем коде еще ни одного дженерика не написал где это понадобиться могло бы, а дженериков тонна.
ПК> Плюс можно пойти далее, но это для C# generics, очевидно, вообще, другая планета: ПК>http://www.cs.rpi.edu/~musser/gp/ ПК>http://www.boost.org/more/generic_programming.html
Ну, т.е. пример именно обобщенного алгоритма не реализуемого на шарпе ты привести не в силах, но дальше кидашся ссылками и с понтом рассуждаешь про другие планеты? Или к обобщенному программированию имеют отношение "Type Generators" и другая метапрограммная бустовская хрень?
>> И какою качественную разницу ты видишь между дженериками и шаблонами?
ПК>В возможностях: шаблоны позволяют применять к объектам типов, заданных параметрами шаблона, любые операции, которые можно использовать вне шаблонов. Generics не позволяют.
>> ПК> Уже написано. <boost/operators.hpp>
>> Значит операторы уже мовитон?
ПК>Моветон не операторы, а copy-paste.
>> ПК> Теперь вернемся к примеру выше, и ответим на вопрос: является ли конструкция ниже примером "статически типизированного программирования": >> ПК>
>> Нет. Но причем тут эта конструкция?
ПК>При том, что это был единственный способ, который ты нашел, чтобы избавиться от copy-paste при использовании generics. И к обобщенному программированию этот способ не относится.
>> Вот эти конструкции
являются. К дженерикам относятся именно оин.
ПК>Этими средствами не получается выйти за рамки интерфейсов. Приходим к тому, с чего начали: кроме избавления от приведений типов generics ничего по сравнению с "обычными" классами не дают. (как верно было замечено, можно добавить избавление от boxing/unboxing, но сути это не меняет)
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, prVovik, Вы писали:
V>Здравствуйте, VladD2, Вы писали:
VD>>Тут и параметризация константами, V>Ну и что? Или если этого нет в генериках, то оно автоматически сразу становится метопрограммированием?
Нет или есть тут не причем. Но параметризация константами никакого отношения к обобщенному программированию не имеет. Обобщенное — значит применимое для любого типа. Параметризация же константами — это чистый макросный стиль, или метапрограммирование.
VD>>и изменение структуры кода при изменении параметра типа. V>Семантически код абсолютно не меняется. То, что там происходит на уровне ассемблера, мне по барабану.
Если константы просто подставляются, то тоже самое можно добиться простым заданием констант в классе или заменой их на переменные. Если же константы начинают влиять на алгоритм (менять код), то это четкий признак применения шаблонов для метапрограммирования.
VD>>Натуральная кодогенерация. И потому легко решается с помощью макросов и кодогенераторов. V>А list<T> — это тоже натуральная кодогенерация? Ведь оно тоже "легко решается с помощью макросов и кодогенераторов"?
Еесли классы/методы отличаются только абстрагированностью от конкретных типов, то это обобщенное программирование. Если имеется элементы кодогенерации — это это уже нечто выходящее за рамки обобщенного программирования.
Несмоненно с помощью метапрограммирования можно эмулировать практически любые расширения ЯП, но это уже отдельный вопрос имеющий опосредованное отношение.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, McSeem2, Вы писали:
MS>Наверное не я. Напомни-ка.
Ну, возможно не ты. Сейчас найти уже тяжело.
MS>Я помню то, что я говорил о необходимости иметь встроенный в язык макропроцессор, а не привешенный сверху. Но это уже — совсем другой коленкор.
Я так понимаю — это очередной комплекс пасивности. Если чего-то нет, то этого нет в принципе... Позиция обычно стречается у молодых и не оптыных. От тебя слашать такие слова странно.
Я предпочитаю другую позицию... Есть задача, и есть средства. Если средств нехватает, то я думаю как их создать или использовать некий гибрид.
MS>Я не размножаю — они сами размножаются. И главное средство их размножения — это тот самый copy-paste. А я их стараюсь давить — душили-душили, душили-душили...
Хреново ты их давишь. У меня вот ничто само не размножается.
MS>Это не религия не позволяет — это практика не позволяет. Вот представь, что я отдаю исходник на C# или Java заказчику весь в дефайнах и ифдефах, и говорю — а компилируйте через cpp.exe и всех делов. В какое место я буду послан?
Думаю, что эту ситуацию ты только что сам придумал. Зачем заказчику исходный код? Им продукт нужен. Если они исходники и возьмут, то только в качестве защиты от тебя любимого, чтбы если что отдать их другому программисту. И уж смотреть на то чем что компилируется точно не будут. Им достаточно будет сказать, что для компиляции нужно иметь установленную VS.
MS>Короче говоря, надо пользоваться естественными средствами языка. Сишный препроцессор для Си — естественное явление — просто берешь и компилируешь. Тот же самый препроцессор для C# — нонсенс.
Ествественно все что удобно. Если ты в своей голове не можешь уйти дальше стереотипов и штампов, то это твои личные проблемы.
Использовать С-шный препроцессор в Шарпе большинство не будет по совсем другим причинам. Проблем от него куда болше чем пользы. Код сгенерировать можно и на других средствах. Причем получится и проще, и удобнее и безопаснее. Отладка шаблонов и потенциальные проблемы от них — это очень плохое поспорье для больших проектов.
MS>Представь, вот просто представь — кто-то решил внести свой вклад в R# и пишет код, который надо обрабатывать Сишным препроцессором. В какое место ты сам его пошлёшь? И будешь прав, что характерно.
С-шный прероцессор — это дерьмо. Его возможности с R# и рядом не стояли. Именно по этому R# делается на R#-е. И именно по этому в нем нет С-шного препроцессора. Ведь если бы С-ный препроцессор был нормальным решением, то R# просто был бы не нужен.
VD>>А по уму твоя проблема решается кодогенератором. Качаешь R# или КодСмит и через пять минут решение твоей неразрешимой проблемы. Причем чистое, красивое, и легко отлаживаемое.
MS>О! Насчет "чистое и красивое" — это станет возможным только тогда, когда этот самый R# будет встроен в язык и стандартную поставку.
Ну, для примитивных личностей с трудом освоивших текстовый процессор наврно. А так... лигического обоснования необходимости быть встроенным в язык я не вижу.
Конечно было бы не плохо продумать все моменты более детально и сделать работу с метакодом и его результатом боле удобным. Однако и это не означает встраивания в язык.
Простой пример... В Шарп 2.0 встроены итераторы. Их с успехом можно было сделать на R#-е уже сейчас. Причем выглядело бы это точно так же как сейчас. Вот только алгоримт работы итераторов можно было бы сделать куда более гибким и настраиваемым. Думаю, когда нибудь это появится и в средсвах разработки от иминитых поставщиков. Ну, а пока те кто по линивее и по тупее будут ждать милости от природы, а мы потихоньку возмем их сами.
MS> Когда это случится? Насчет "легко отлаживаемое" — не верю вообще.
Я я не привых здать реализации счастья большими дядями. У меня своя голова и руки есть.
MS>Ну, и как это дело трассировать в отладчике (вне зависимости от языка)? Как это решено в кодогенераторе R#? MS>Здесь только два варианта — либо трассировать не исходный текст, а результат работы кодогенератора (представь, что Сишный отладчик выдает не исходник, а некую абракадабру после обработки препроцессором), либо же не трассировать вообще — как в случае Сишных макросов. Третий вариант — отладчик должен умно разворачивать данные конструкции — типа как при трассировке ассемблерного кода в студии. А это означает, что отладчик должен знать, что есть такое слово, как R#. Так когда это все будет? Мы ждем с нетерпением...
Ты затронул довольно сложную тему. Я сам много раз думал над этим. То как сделано в современных средах С/С++ — это точно никуда не годящееся решение. Отладка сложных макросов — это полнейший мрак.
Пока что лично я склоняюсь к отладке по сгенерированному коду. В принципе уже многие консрукции порождающие сложный код можно и не раскрывать. Но это уже после того как они были отлажены. А на этапе отладки необходимо иметь возможность отладки по генерируемому коду. В приципе это решается за счет атрибутов и фич вроде #line.
Однако особо сложные случаи вроде реализация иерархий классов, паттернов проектирования и т.п. приводит к слишком большому объему генерируемого кода. Тут без работы со сгенерированным кодом будет просто некуда. По этому наврено имеет смысл иметь два варианта. Один работа по генерируемому коду, второй по исходной модели. Ну, и иметь возможность переключаться между ними.
В общем, эта тема заслуживает отдельного обсуждения. И говорить о ней вот так между делом бессмысленно. Проблема или имеет свое решение, и тогда для ее решения совершенно нет нужны что-то куда-то интегрировать. Или не имеет, но тогда все рассуждения об интеграции опять же бессмысленны.
MS>В общем, благодаря этой дискуссии я наконец-то понял, что шаблоны отличаются от макросов тем, что код шаблонов можно трассировать, а код макросов — нельзя. Шаблоны — страшная сила!
Шаблоны главным образом отличаются от макросов тем, что они синтаксически управляемы. Они не генерят текст. Они генерят АСТ. Собственно это же делает и R#. А отлаживать их проще потому, что они не имеют штатных средств генерации кода. Но как только путем использования побочных эффектов с помощью макросов начинают генерировать код, то отладка оного становится невыносимо тежелой. Ведь в рекурсивных шаблонах точку остонова не поставишь. И результат генерируемых Локи кодов увидить в общем-то нельзя. Все только подразумевается, а — это уже перегрузка мозгов. Причем совершенно не нужная.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Легко. Они будут порождаться клиентом. "Рабочий" код будет в .dll.
На базе чего они будут порождаться? В длл может быть только специализация. Так что или длл не нужна, так как весь код в заголовочном файле, или мы не может порождать специализаций не предусмотренных в длл-е.
>> А можно узнать что нового привносят в данном разрезе шаблоны?
ПК>Кроме переноса диагностики в статуку — замена copy-paste. Везде, где нужно было копировать код, можно заменить это на шаблон. Generics полностью эту задачу не решают.
Чушь. И ты это знаешь.
ПК>Ага. Для int, например.
А чем он отличается если мы плюем на производительность? В те же Питонах и лиспах int-ы — это такие же ссылочные типы. Потому они так полиморфны. Плата только в скорости и статической типизации.
ПК>Можно и по-другому повернуть: ты уже 4 часа откровенно не понимаешь, где черное, а где белое, да еще и хамишь. Мне это уже порядком надоело.
Я называю вещи своими именами. Откровенно непрыкрытое нежелание признавать очевидные вещи я так и называю. И если ты называшь мои слова хамством, то твои никак кроме лицемерия назвать не получается.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, prVovik, Вы писали:
V>Здравствуйте, VladD2, Вы писали:
VD>>В отсуствии необходимости применения боксинга, наследования, виртуальных методов. В применимости к вэлью-типам. В общем, во всем в том, что касается и шаблонов. В итоге статическая типобезопастность и повешение скорости.
V>Ага, то есть ты признаешь, что с семантической точки зрания генерики не привносят ничего, кроме отсутствия необходимости делать приведения типов, а все их остальные бонусы сводятся к оптимизации?
Дженерики привросят качественное изменение. Они позволяют писать статически проверяемый код для набора неких абстрактных типов. Именно для этого и были в свое время созданны шаблоны.
Это качественное отличие.
Можно ли без него жить? Можно.
Можно ли решать задачи без обобщенного программирования? Можно.
Является ли динамический полиморфизм нормальной заменой статическому? Нет.
V>Ну если так, то я напомню, что возможности по оптимизации, предоставляемые генериками — это просто ДЕТСКИЙ САД, по сравнению с оптимизацией на шаблонах! Надеюсь, это доказывать не придется?
Это заблуждение. И как любое заблуждение его доказывать не нужно.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> ПК>Легко. Они будут порождаться клиентом. "Рабочий" код будет в .dll.
> На базе чего они будут порождаться? В длл может быть только специализация. Так что или длл не нужна, так как весь код в заголовочном файле, или мы не может порождать специализаций не предусмотренных в длл-е.
Нет, код может быть в DLL, а в заголовочном файле — только переходники для "автоматического" приведения типов. Например (псевдокод):
interface I
{
void f();
void g();
. . .
};
Для такого "generic" класса:
class G<T> where T : I
{
public void a(T) { /* ... some long and complex code ... */ }
public T b() { /* ... some long and complex code ... */ }
. . .
};
можно сделать такую комбинацию шаблона с "обычным" классом, реализация которого будет в DLL:
[dllexport]
class G_
{
public:
void a(I&); // some long and complex code is in the DLL
I& b(); // some long and complex code is in the DLL
};
template<class T>
class G : private G_
{
BOOST_STATIC_ASSERT( boost::is_convertible<T*,I*>::value );
public:
void a(T& t) { G_::a(t); }
T& b() { return dynamic_cast<T&>( G_::b() ); }
};
В классе G_ с аргументами можно делать то же, что и в "generic" G<T>, т.к. за пределы интерфейса I выйти в "generic" классе в C# все равно нельзя.
> ПК> Ага. Для int, например.
> А чем он отличается если мы плюем на производительность? В те же Питонах и лиспах int-ы — это такие же ссылочные типы.
В Лиспе и Питоне — да. В C# — нет. В Лиспе и Питоне, например, с разными арифметическими типами можно работать полиморфно. В C# — очень ограниченно, по сути, нельзя. В C++ шаблоны дают возможность работать с арифметическими типами полиморфно. Generics в C# — нет.
> ПК> Можно и по-другому повернуть: ты уже 4 часа откровенно не понимаешь, где черное, а где белое, да еще и хамишь. Мне это уже порядком надоело.
> Я называю вещи своими именами.
И ты точно знаешь, что представляет из себя каждая вещь, и какое у нее имя? Ну-ну.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
VD>На базе чего они будут порождаться? В длл может быть только специализация. Так что или длл не нужна, так как весь код в заголовочном файле, или мы не может порождать специализаций не предусмотренных в длл-е.
Не, ты не понял. В длл плмещается полиморфный код, а в заголовочном файле — типобезопасная обертка для него.
Здравствуйте, VladD2, Вы писали:
VD>Дженерики привросят качественное изменение. Они позволяют писать статически проверяемый код для набора неких абстрактных типов. Именно для этого и были в свое время созданны шаблоны.
Об этом я и говорю.
VD>Это качественное отличие.
Согласен. Об этом и толкую, что их единственное качественное свойство — это типобезопасность, вызванная отсутствием необходимости приведений типов на этапе выполнения программы.
VD>Можно ли без него жить? Можно. VD>Можно ли решать задачи без обобщенного программирования? Можно. VD>Является ли динамический полиморфизм нормальной заменой статическому? Нет.
Точно.
VD>Это заблуждение. И как любое заблуждение его доказывать не нужно.
То есть? Не понял, что ты имеешь ввиду. Поясни.
Здравствуйте, prVovik, Вы писали:
V>Здравствуйте, VladD2, Вы писали:
VD>>Обобщенное — значит применимое для любого типа. V>Свойства типов могут зависеть от констант (например, размер), поэтому константы можно рассматривать, как механизм доопределения типов.
В дотнете типы не могут зависеть от констант. От констант могут зависить только экземпляры. Так что это не аргумент.
V> И вообще, само слово "обобщенный" означает независимый от частностей. В качестве таких честностей вполне могут выступать не только типы, но и константы. Почему нет?
По определению.
VD>>Параметризация же константами — это чистый макросный стиль, или метапрограммирование. V>спорно
Оспорить можно все.
VD>>Если константы просто подставляются, то тоже самое можно добиться простым заданием констант в классе или заменой их на переменные. V>Совершенно верно. Точно так же, как статический полиформизм вегда можно заменить динамическим. Ситуация абсолютно идентична.
Это обратная аналгия. То что что-то похожее не дает ни малейшего основания для выводов на этой основе.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Нет, код может быть в DLL, а в заголовочном файле — только переходники для "автоматического" приведения типов.
Понятно. Пошли выдумывать неотносящиеся к делу случая чтобы оправдать свои слова. Мы вроде говорили об экспорте шаблона из библиотеки. Ну, и не нужно сваливаться на необобщенные интерфейсы. Они тут не причем.
ПК>В Лиспе и Питоне — да. В C# — нет. В Лиспе и Питоне, например, с разными арифметическими типами можно работать полиморфно. В C# — очень ограниченно, по сути, нельзя. В C++ шаблоны дают возможность работать с арифметическими типами полиморфно. Generics в C# — нет.
Создай обертку над типом и предстваь все операции в виде методов. Далее проблем с полиморфными алгоритмами не будет. Это на любом языке поддерживающем полиморфизм можно сделать. Хоть на С.
ПК>И ты точно знаешь, что представляет из себя каждая вещь, и какое у нее имя? Ну-ну.
Я и не утвреждаю, что знаю все. Но очевидные вещи есть очевидные вещи. Даже если прийдет 100 экспертов-художников и скажут мне, что белое — это черное я останусь при своем мнеии.
Заявления типа "дженерики непригодны для обощенного программирования, они неполноценны" стольк очивидно бредовые, что с ними даже нельзя спорить.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, prVovik, Вы писали:
VD>>Это качественное отличие. V>Согласен.
Вот Паша не согласен. Религия не позволяет. Шаблоны типа полноценный инструмент обобщенного программирования, а дженерики эдакие приводилки типов.
V> Об этом и толкую, что их единственное качественное свойство — это типобезопасность, вызванная отсутствием необходимости приведений типов на этапе выполнения программы.
Блин. Да нет в обобщенном программировании понятия "избавление от приведения тиов". Это законченная парадигма. И, кстати, никто не мешает заниматься обобщенным приведением типов и писать динамически типизированный код. Хоть так:
T MyCast<T>(object obj)
{
return (T)obj;
}
VD>>Это заблуждение. И как любое заблуждение его доказывать не нужно. V>То есть? Не понял, что ты имеешь ввиду. Поясни.
Пояснить то что твои слова являются заблуждением? Может это ты пояснишь из какого пальца высасоны твои выводы? Дженерики без всяких оптимизаций делают код значительно более эффективным нежели аналогичный полиморфный. И никаких причин их по оптимизации я вроде бы не вижу. Ты на них тоже не указывал. Взял так и высосал из пальца "оптимизации, предоставляемые генериками — это просто ДЕТСКИЙ САД".
Детский сад — это подбные заявления.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Блин. Да нет в обобщенном программировании понятия "избавление от приведения тиов". Это законченная парадигма. И, кстати, никто не мешает заниматься обобщенным приведением типов и писать динамически типизированный код. Хоть так: VD>
VD>Взял так и высосал из пальца "оптимизации, предоставляемые генериками — это просто ДЕТСКИЙ САД".
А может не стоит выдергивать фразы из контекста? Я сказал следующее:
возможности по оптимизации, предоставляемые генериками — это просто ДЕТСКИЙ САД, по сравнению с оптимизацией на шаблонах!
То есть ты не согласен с тем, что шаблоны предоставляют на порядок больше возможностей для оптимизации, чем генерики? Я правильно тебя понял?
Здравствуйте, prVovik, Вы писали:
VD>>Речь шла о шаблонах, об экспорте шаблонов. Причем тут твои слова? V>С точки зрения пользователя библиотеки, он оиспользует обычный типобезопасный шаблон со статическим контролем типов. При этом, весь реально работающий код находится в длл, которую можно менять. И чем это ПРИНЦИПИАЛЬНО будет отличаться от генериков?
Тем что дженерики можно положить в длл и использовать их без исходников прямо в бинарном виде. А шаблоные нельзя.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Тем что дженерики можно положить в длл и использовать их без исходников прямо в бинарном виде. А шаблоные нельзя.
Так, еще разок:
При этом, весь реально работающий код находится в длл, которую можно менять.
Здравствуйте, VladD2, Вы писали:
VD>Вот это сказка.
Попробую объяснить. Допустим, мы хотим сделать типобезопасный обобщенный список и экспортировать его в длл.
///////////////////////////////////////////////////////////////////////////////////////
// заголовочный фал, поставляемый с библиотекой.
///////////////////////////////////////////////////////////////////////////////////////
// этот класс реально экспортируется в длл, но пользователем напрямую не используетсяclass MyArrayListImpl
{
public:
void Add( void *item );
void* GetItem( int index );
...
};
// а это уже реально используемый пользователями шаблон. Не содержит абсолютно никакого кода,
// а только делегирует к MyArrayListImpltemplate< class T >
class MyArrayList: public MyArrayListImpl
{
public:
void Add( T item )
{
MyArrayListImpl::Add( item );
}
T Get( int index )
{
return (T)MyArrayListImpl::GetItem(index);
}
...
};
///////////////////////////////////////////////////////////////////////////////////////
// клиентская программа
///////////////////////////////////////////////////////////////////////////////////////struct SomeStruct
{
...
};
...
MyArrayList<SomeStruct*> arlst;
arlst.Add( new SomeStruct() );
void *ptr = arlst.Get(0); // ОШИБКА КОМПИЛЯЦИИ.
То есть, таким образом, мы получили статический контроль типизации нетипизированной динамически загружаемой библиотеки.
VladD2,
> VD>>Тем что дженерики можно положить в длл и использовать их без исходников прямо в бинарном виде. А шаблоные нельзя.
> V> Так, еще разок: > V>
При этом, весь реально работающий код находится в длл, которую можно менять.
> Вот это сказка.
Влад, не смешно. Перечитай предлагавшиеся варианты (выше по ветке). Т.к. generics ограничены возможностями работы через интерфейсы, то можно вынести соответствующие non-generic функции, работающие через ссылки и указатели на интерфейсы, в DLL. Что конкретно не будет работать?
Posted via RSDN NNTP Server 2.0 alpha
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, prVovik, Вы писали:
V>То есть, таким образом, мы получили статический контроль типизации нетипизированной динамически загружаемой библиотеки.
Это, я извинясь, хрень полная, а не шаблон в библиотеке. Что и следовало доказать. В то же время дженерики лежат себе в библоиотеках и даже описания текстового не просят. Потому как проектировались в рассчете на это.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
ПК>Влад, не смешно. Перечитай предлагавшиеся варианты (выше по ветке). Т.к. generics ограничены возможностями работы через интерфейсы, то можно вынести соответствующие non-generic функции, работающие через ссылки и указатели на интерфейсы, в DLL. Что конкретно не будет работать?
Ничего не будет работать. Положить полноценный шаблон в длл невозможно. А дженерик раз плюнуть.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Костя Ещенко, Вы писали:
КЕ>Чтобы использовать extern "C" функцию, определенную в dll, тоже нужно текстовое объявление. И это не мешает их широкому использованию.
Ато разные вещи. Функция все не меняется от передачи ей других параметров. А вот шаблон меняется. И в библиотеке может лижать только специализация шаблона. А вот жденерики лежат себе целиком и прекрасно работают.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>_FRED_,
ПК>Извиняюсь, что посреди большой философии с такими частностями. Тем не менее...
Эээ. Такую тему пропустил....
>> Читал, что экспорт шаблонов ещё не сделан.
ПК>Сделан в EDG. Сравнительно давно доступен в Comeau.
>> Нужен? "Необходим!" ответят, я думаю, многие.
ПК>Уверяю, не необходим. Кой-какая польза от него есть, но не принципиальная. Заключается в том, что при наличии экспорта шаблонов можно перекомпилировать не все файлы, зависящие от определения изменившегося шаблона, а только один из них.
Нет реальная польза не в этом. См. ниже. При перекомпиляции, кстати, не так всё гладко. Но даже если бы не было никаких приемуществ для компиляции, всё равно экспорт нужен.
> Имхо, намного полезнее введение модулей, чему, впрочем, экспорт шаблонов, вроде, не мешает.
Абсолютно. Экспорт шаблонов требует рассмотрения исходных файлов за пределами единицы трансляции (в её привычном понимании). В каком-то смысле экспорт форсирует переход к модульной компиляции в C++. Это одна из причин, по которой экспорт отвергается многими производителями компиляторов. Не расчитаны они на модульный подход. Даёшь им единицу трансляции в один файл и всё тут.
ПК>Хотя, согласен, практического опыта использования экспорта шаблонов пока наработано немного, может оказаться, что какие-то дополнительные бонусы еще не найдены.
А как насчёт сокрытия реализации? Не надоели вещи типа namespace details?
По мне так плевать на раздельную компиляцию, но сокрытие реализации подайте. В этом смысле бонусы абсолютно такие же, как и при разделении нешаблонного кода на интерфейс и реализацию.
<rant>А опыт не накоплен, потому что кому-то даже лень разжиться Comeau C++ за $20!</rant>
alexeiz,
> В каком-то смысле экспорт форсирует переход к модульной компиляции в C++.
Скорее, к компиляции всей программы...
> ПК>Хотя, согласен, практического опыта использования экспорта шаблонов пока наработано немного, может оказаться, что какие-то дополнительные бонусы еще не найдены. > > А как насчёт сокрытия реализации? Не надоели вещи типа namespace details?
Да, этот момент присутствует, но не в той мере, как ожидалось до реализации и практического опыта. Даже при экспорте вполне могут "подхватываться" функции из других единиц трансляции, в т.ч. и из анонимных namespace, из-за ADL.
В этом смысе настоящая модульная компиляция, имхо, была бы намного лучшим решением, чем экспорт шаблонов.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>alexeiz,
>> ПК>Хотя, согласен, практического опыта использования экспорта шаблонов пока наработано немного, может оказаться, что какие-то дополнительные бонусы еще не найдены. >> >> А как насчёт сокрытия реализации? Не надоели вещи типа namespace details?
ПК>Да, этот момент присутствует, но не в той мере, как ожидалось до реализации и практического опыта.
Ожидалось, что с экспортом шаблонов будет как в Си — изменил один файл реализации, перекомпилировал только его. Не тут-то было.
Я не понимаю, про какой практический опыт ты говоришь. Его просто не существует. Про практический опыт должен говорить Plauger, так как только у него есть библиотека использующая export. Остальные это дело игнорируют, а Plauger молчит как рыба.
>Даже при экспорте вполне могут "подхватываться" функции из других единиц трансляции, в т.ч. и из анонимных namespace, из-за ADL.
То что ты говоришь, касается раздельной компиляции. По причине подхватывания невозможно перекомпилировать только одну единицу трансляции. Я же говорю про разделение интерфейса и реализации на уровне исходных файлов. Мне не так важно будет ли перекомпилирован один файл или несколько. Мне важно, чтобы можно было иметь "чистые" header файлы описывающие только интерфейс библиотеки доступный извне. Я хочу запихать все эти namespace details в далёкое тёмное место. Однако, при современном состоянии дел с шаблонами это невозможно. Экспорт как раз и решает эту проблему.
ПК>В этом смысе настоящая модульная компиляция, имхо, была бы намного лучшим решением, чем экспорт шаблонов.
Как я понял, это ортогональные вещи. Если есть модульная компиляция, то экспорт должен реализоваваться на ура, так как он в этом случае будет представлять только синтаксическую конструкцию, не приводящюю к изменению процесса компиляции.
Кстати про модульную компиляцию. Какие нибудь предложения в С++ коммитет на этот счёт есть? Где нибудь можно посмотреть?
alexeiz,
>> Даже при экспорте вполне могут "подхватываться" функции из других единиц трансляции, в т.ч. и из анонимных namespace, из-за ADL.
> То что ты говоришь, касается раздельной компиляции. По причине подхватывания невозможно перекомпилировать только одну единицу трансляции. Я же говорю про разделение интерфейса и реализации на уровне исходных файлов. Мне не так важно будет ли перекомпилирован один файл или несколько. Мне важно, чтобы можно было иметь "чистые" header файлы описывающие только интерфейс библиотеки доступный извне. Я хочу запихать все эти namespace details в далёкое тёмное место. Однако, при современном состоянии дел с шаблонами это невозможно. Экспорт как раз и решает эту проблему.
В общем случае не решает, т.к. файлы с namespace details "вдруг" могут сослаться из далекого темного места на функции в твоих файлах реализации, даже если непосредственно их не включают. Соответственно, той степени изоляции между интерфейсами и реализацией, как в других местах в C++, не получается.
> ПК>В этом смысе настоящая модульная компиляция, имхо, была бы намного лучшим решением, чем экспорт шаблонов. > > Как я понял, это ортогональные вещи. Если есть модульная компиляция, то экспорт должен реализоваваться на ура, так как он в этом случае будет представлять только синтаксическую конструкцию, не приводящюю к изменению процесса компиляции.
Не факт. При модульной компиляции семантика может отличаться от того, что получилось в случае экспорта.
> Кстати про модульную компиляцию. Какие нибудь предложения в С++ коммитет на этот счёт есть? Где нибудь можно посмотреть?
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>alexeiz,
>>> Даже при экспорте вполне могут "подхватываться" функции из других единиц трансляции, в т.ч. и из анонимных namespace, из-за ADL.
>> То что ты говоришь, касается раздельной компиляции. По причине подхватывания невозможно перекомпилировать только одну единицу трансляции. Я же говорю про разделение интерфейса и реализации на уровне исходных файлов. Мне не так важно будет ли перекомпилирован один файл или несколько. Мне важно, чтобы можно было иметь "чистые" header файлы описывающие только интерфейс библиотеки доступный извне. Я хочу запихать все эти namespace details в далёкое тёмное место. Однако, при современном состоянии дел с шаблонами это невозможно. Экспорт как раз и решает эту проблему.
ПК>В общем случае не решает, т.к. файлы с namespace details "вдруг" могут сослаться из далекого темного места на функции в твоих файлах реализации, даже если непосредственно их не включают. Соответственно, той степени изоляции между интерфейсами и реализацией, как в других местах в C++, не получается.
Это-то понятно. Но мой аргумент в том, что этой степени изоляции и не нужно. Достаточно "визуальной" изоляции. Т.е. я декларирую интерфейс шаблона в .h файле, а реализацию в .cpp. И выглядит это почти так же как и со всем остальным (нешаблонным) кодом.
>> ПК>В этом смысе настоящая модульная компиляция, имхо, была бы намного лучшим решением, чем экспорт шаблонов. >> >> Как я понял, это ортогональные вещи. Если есть модульная компиляция, то экспорт должен реализоваваться на ура, так как он в этом случае будет представлять только синтаксическую конструкцию, не приводящюю к изменению процесса компиляции.
ПК>Не факт. При модульной компиляции семантика может отличаться от того, что получилось в случае экспорта.
>> Кстати про модульную компиляцию. Какие нибудь предложения в С++ коммитет на этот счёт есть? Где нибудь можно посмотреть?
ПК>Daveed Vandevoorde. Modules in C++ (Revision 1) ПК>http://open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1778.pdf
Не очень впечатлило. Ну да это только первый вариант. Есть сомнительные вещи такие как вложенные модули или включение одного модуля в другой. Какие-то модульные атрибуты предлагаются. А вот разделение областей видимости (private поля вообще из модуля никак не видно) — это хорошо. Но вообщем тяжеловато. Надеюсь, это эвалюционирует в более стройную и простую концепцию.