Дальше можно не читать. Одно только то, что ты ставишь макросы и шаблоны в один ряд, красноречиво говорит о твоей квалификации. Как говорится, у Вас не тридцатилетний опыт — у Вас годичный опыт, повторенный тридцать раз.
Т.е. заклеймили даже за саму попытку поставить в один ряд. И мне не ясно почему.
Это тот же шаблон класса, только с помощью макросов. И в чем ключевая разница? Что я так уж потерял?
Ну да, нужно для каждого типа написать эту строчку DECLARE_CLASS1(TTT). Это не удобно. Но по сути — синтаксический сахар. Разницы пока принципиальной нет.
Все равно каждый шаблон раскрывается в момент компиляции. Он должен быть целиком и полностью определен в заголовочном файле — нельзя разнести декларацию и дефиницию, как с обычной функцией или классом. С макросом та же проблема.
Возможно чего нельзя сделать макросами — это частичная специализация шаблонов (а может и можно придумать как). Что еще?
S>Дальше можно не читать. Одно только то, что ты ставишь макросы и шаблоны в один ряд, красноречиво говорит о твоей квалификации. Как говорится, у Вас не тридцатилетний опыт — у Вас годичный опыт, повторенный тридцать раз.
S>Т.е. заклеймили даже за саму попытку поставить в один ряд. И мне не ясно почему.
S>Дальше можно не читать. Одно только то, что ты ставишь макросы и шаблоны в один ряд, красноречиво говорит о твоей квалификации. Как говорится, у Вас не тридцатилетний опыт — у Вас годичный опыт, повторенный тридцать раз.
S>Т.е. заклеймили даже за саму попытку поставить в один ряд. И мне не ясно почему.
Тезисно:
Шаблоны обрабатываются копилятором, а макросы обрабатываются препроцессором
Макросы не подчиняются правилам пространств имен и областей видимости
Макросы не подчиняются правилам поиска имен — name lookup и argument-dependent name lookup
Для макросов недоступны специализации и перегрузки
Для макросов не предусмотрено ничего похожего на отложенное (неявное) инстанцирование, которое очень востребовано при использовании шаблонов.
Макросы не могут рекуррентно использовать сами себя.
Для макросов недоступно огромное количество инструментов и паттернов, доступных для шаблонов — концепты, SFINAE, CRTP, variadic packs, template class argument deduction и пр.
Макросы небезопасны в плане скрытых побочных эффектов (классический пример — max(++a, ++b))
Макросы существенно проблематичнее в отладке и поиске ошибок, чем шаблоны.
Наверняка, еще есть что-то, что я навскидку не смог вспомнить
Первый пункт выделен, потому что он мне представляется ключевым и из него следует все остальное. Препроцессор гораздо примитивнее компилятора, его задача — подготовка текста программы для компилятора. У него на входе текст, и на выходе тоже текст. Злоупотребление препроцессором для эмуляции программных сущностей (функций и классов) является использованием инструментов не по назначению. Это сродни открыванию консервных банок молотком, или изготовлению мебели топором.
Здравствуйте, Pzz, Вы писали:
Pzz>Чел. очень категоричен.
В чем именно я ОЧЕНЬ категоричен? В том, что макросы существенно отличаются от шаблонов по своим возможностям? Или в высказывании о том, что макросами не следует злоупотреблять? В чем конкретно?
S>Вот код: S>Это тот же шаблон класса, только с помощью макросов. И в чем ключевая разница? Что я так уж потерял?
Разница не очень очевидна, только благодяря примитивности примера. А ты попробуй, реализавать что-нибудь посложнее — тот же std::vector, например, или std::string, только ничего не упрощая. Или какие-нибудь метафункции из type_traits.
Попробуй, в качестве упражнения, реализовать на макросах компайл-тайм факториал, который мы недавно обсуждали. Я не говорю, что это совсем невозможно — возможно — с некоторыми ограничениями. Но это стоит сделать ради того, чтоб прочувствовать разницу.
Здравствуйте, rg45, Вы писали:
Pzz>>Чел. очень категоричен.
R>В чем именно я ОЧЕНЬ категоричен? В том, что макросы существенно отличаются от шаблонов по своим возможностям? Или в высказывании о том, что макросами не следует злоупотреблять? В чем конкретно?
В том, что макросы существенно отличаются от шаблонов — тут ты прав. И в том, что ими не стоит злоупотреблять — тут ты тоже прав. А вот в оценке квалификации своего оппонента — очень категоричен. Вообще не понимаю, зачем было на личности переходить.
И ты учти еще такую вещь. Твой оппонент всегда работает один. Может, у него рука набита на макросах, и он в них никогда не ошибается. У него свои правила и предпочтения, выработанные с учетом его личного опыта. Когда работаешь один, это не то же самое, чем когда работаешь с другими людьми, особенно в лидерской позиции. В первом случае ты просто делаешь, как удобно именно тебе. Во втором случае, люди на тебя равняются, и не надо вносить небезопасные практики (пусть даже лично для тебя они вполне безопасные).
В этой книжке автор определяет 3 вида макросов: текстовые, синтаксические и вычислительные (третий термин, возможно, уже попутал)
Основная операция макросов — подстановка.
Текстовый вид макросов все знают.
Синтаксические макросы — это подстановка на этапе компиляции с проверкой получившегося синтаксиса.
Как все, надеюсь, понимают, шаблоны — это разновидность синтаксических макросов по классификации Кемпбела-Келли.
Кстати, был в свое время такой компилятор Clipper для языка Dbase II
Там в 5-й версии синтаксические макросы расцвели просто невообразимо.
Не помню про вычислительные макросы — надо перечитать.
Но в С++ есть инлайн-функции, где на место вызова функции подставляется ее тело.
Возможно, это они и есть.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
S>Дальше можно не читать. Одно только то, что ты ставишь макросы и шаблоны в один ряд, красноречиво говорит о твоей квалификации. Как говорится, у Вас не тридцатилетний опыт — у Вас годичный опыт, повторенный тридцать раз.
S>Т.е. заклеймили даже за саму попытку поставить в один ряд. И мне не ясно почему.
Зря заклеймили. Если совсем в принципе, там ведь верно написано, это все для одного и того же — для генерации кода в compile-time, функциональное программирование тут ни при чем.
Просто нормальной реализации мета-программирования, чтобы код генерировал другой код во время компиляции, и с этим было комфортно работать, пока нет, особенно в плюсах.
У плюсовых макросов полно недостатков, да и у шаблонов тоже.
Здравствуйте, Pzz, Вы писали:
Pzz>В том, что макросы существенно отличаются от шаблонов — тут ты прав. И в том, что ими не стоит злоупотреблять — тут ты тоже прав. А вот в оценке квалификации своего оппонента — очень категоричен. Вообще не понимаю, зачем было на личности переходить.
А, ты об этом... Может, и не стоило. Больно уж рассердил он меня своими предыдущими постами и воинствующим невежеством.
Здравствуйте, bnk, Вы писали:
bnk>Зря заклеймили. Если совсем в принципе, там ведь верно написано, это все для одного и того же — для генерации кода в compile-time
Макросы — это ни разу не про компайл тайм — это просто манипуляции с текстом программы, выполняемые ДО передачи этого тескта компилятору. И непонимание принципиальных различий между макросами и шаблонами — это стыдно (для того, кто претендует на звание опытного разработчика С++).
S>Дальше можно не читать. Одно только то, что ты ставишь макросы и шаблоны в один ряд, красноречиво говорит о твоей квалификации. Как говорится, у Вас не тридцатилетний опыт — у Вас годичный опыт, повторенный тридцать раз.
+1
S>Т.е. заклеймили даже за саму попытку поставить в один ряд. И мне не ясно почему. S>
S>Это тот же шаблон класса, только с помощью макросов. И в чем ключевая разница? Что я так уж потерял?
S>Ну да, нужно для каждого типа написать эту строчку DECLARE_CLASS1(TTT). Это не удобно. Но по сути — синтаксический сахар. Разницы пока принципиальной нет.
S>Все равно каждый шаблон раскрывается в момент компиляции.
Один раз с конкретными параметрами. А макрос -- каждый раз.
S> Он должен быть целиком и полностью определен в заголовочном файле.
Никто никому ничего не должен.
S> нельзя разнести декларацию и дефиницию,
Можно декларировать, что есть C<T>, можно отдельно дать определение, если оно нужно.
Ясно, что оно неожиданно становится нужным во многих случаях. Но точно так же и сам
класс можно отдельно объявить, что он де существует ("class name;"), а отдельно дать
определение.
S> как с обычной функцией или классом. С макросом та же проблема.
Макрос это вообще не конструкция языка. Чего сравнивать. Определение шаблона таки
компилируется до превращения в конкретный класс. А макрос -- подстановка именно текста. Любого.
S>Возможно чего нельзя сделать макросами — это частичная специализация шаблонов (а может и можно придумать как). Что еще?
Да практически всё. Начиная с того, что два макроса с одинаковыми параметрами дадут два
РАЗНЫХ класса, даже если абсолютно одинаковых по структуре. А шаблон даст один класс, в котором
в частности будет один набор static-объектов. Не говоря уж про современные нюансы, что у шаблона есть CTAD, например,
Здравствуйте, rg45, Вы писали:
bnk>>Зря заклеймили. Если совсем в принципе, там ведь верно написано, это все для одного и того же — для генерации кода в compile-time
R>Макросы — это ни разу не про компайл тайм — это просто манипуляции с текстом программы, выполняемые ДО передачи этого тескта компилятору. И непонимание принципиальных различий между макросами и шаблонами — это стыдно (для того, кто претендует на звание опытного разработчика С++).
Ты говоришь о технической стороне вопроса, в привязке к плюсам. Под "генерацией кода во время компиляции" имеется в виду все, что происходит от написания кода, до его запуска.
Уж чем он там обрабатывается — дело десятое. Твой "препроцессор" вообще может вообще встроен в "компилятор", и отсутствовать как отдельная сущность.
Как именно производится манипуляция с исходным кодом программы — путем изменения текста, дерева (AST), во время кодогенерации, или еще как, если это хорошо, надежно и удобно работает — совершенно не принципиально.
"Метапрограммирование" на уровне изменения текста работает например в шарпе, и ничего.
Здравствуйте, rg45, Вы писали:
R> Для макросов не предусмотрено ничего похожего на отложенное (неявное) инстанцирование, которое очень востребовано при использовании шаблонов.
В смысле? Макросы как раз и дают результат в месте вызова, отлженно.
R> Для макросов недоступно огромное количество инструментов и паттернов, доступных для шаблонов — концепты, SFINAE, CRTP, variadic packs, template class argument deduction и пр.
Смешаны совершенно разные концепции. SFINAЕ -- краеугольный камень, на котором всё стоит. Остальное всё
постольку-поскольку. Переменное число аргументов есть и у макросов.
R> Макросы небезопасны в плане скрытых побочных эффектов (классический пример — max(++a, ++b))
std::max неожиданно тоже опасен! В него можно подсунуть временнй объект.
R> Макросы существенно проблематичнее в отладке и поиске ошибок, чем шаблоны.
Притянуто за уши. То и другое по шагам не шагается в отладчике, то и другое компиляторы умеют разворачивать
по шагам когда показывают ошибку.
Здравствуйте, fk0, Вы писали:
R>> Макросы существенно проблематичнее в отладке и поиске ошибок, чем шаблоны.
fk0> Притянуто за уши. То и другое по шагам не шагается в отладчике,
Все прекрасно шагается. Да, инстанцирование шаблонных функций выполняется в компайл-тайм, но после этого по инстанцированным функциям можно спокойно ходить обычным run-time отладчиком, как по обычным функциям (если они не constexpr, конечно). Вероятно, ты путаешь constexpr функции с шаблонами функций? Так это полностью ортогональные понятия — constexpr фунцкия не обязательно должна быть шаблонной, а шаблон функции — не обязательно constexpr.
Здравствуйте, Pzz, Вы писали:
Pzz>И ты учти еще такую вещь. Твой оппонент всегда работает один. Может, у него рука набита на макросах, и он в них никогда не ошибается. У него свои правила и предпочтения, выработанные с учетом его личного опыта. Когда работаешь один, это не то же самое, чем когда работаешь с другими людьми, особенно в лидерской позиции. В первом случае ты просто делаешь, как удобно именно тебе. Во втором случае, люди на тебя равняются, и не надо вносить небезопасные практики (пусть даже лично для тебя они вполне безопасные).
Если у "оппонета" столь специфичные условия работы, ему следовало бы быть более аккуратным в высказываниях. Он же постоянно норовит померить всех своим аршином, мол, "если мне не нужно, значит и другим не нужно", "если я не знаю, значит и другие не знают". Вот, недавний пример:
То, что большинство не знает о наличии в языке этой фичи, лишний раз показывает, что ее ценность околонулевая.
Причем, пример далеко не единственный, это стиль. Он же систематически в своих постах объявляет войну всему, чего не знает, или что ему не приходилось использовать. Вроде, он какой-то эталон и язык разрабатывается только под его нужды.
Здравствуйте, bnk, Вы писали:
bnk>Ты говоришь о технической стороне вопроса, в привязке к плюсам. Под "генерацией кода во время компиляции" имеется в виду все, что происходит от написания кода, до его запуска.
Нет, никто здесь не собирался обсуждать, кодгенерацию "вообще". Это конкретный форум и конкретная тема: "Ключевое отличие шаблона от макроса".
P.S. И ключевым я считаю то, что макросы и шаблоны обрабатываются различными компонентами, несопоставимыми по сложности и своим возможностям. Я писал об ээтом здесь: http://rsdn.org/forum/cpp/8559148.1
Здравствуйте, Shmj, Вы писали:
S>Т.е. заклеймили даже за саму попытку поставить в один ряд.
Тут дело вообще не в "попытке поставить". Просто у rg45 ко мне такая личная неприязнь, что он даже кушать не может при виде малейшего расхождения во мнениях сразу вспоминает все наши конфликты за все время присутствия здесь, и никак не упустит возможности уязвить, даже мелко и по-детски.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Тут дело вообще не в "попытке поставить". Просто у rg45 ко мне такая личная неприязнь, что он даже кушать не может при виде малейшего расхождения во мнениях сразу вспоминает все наши конфликты за все время присутствия здесь,
Здравствуйте, Shmj, Вы писали:
S>Он должен быть целиком и полностью определен в заголовочном файле — нельзя разнести декларацию и дефиницию, как с обычной функцией или классом.
Вот это твое заблуждение, обусловленное недостатком знания языка. Определение шаблонов в заголовочных файлах необходимо только для неявного (implicit) инстанцирования. Но, помимо неявного, есть еще и явное инстанцирование (explicit instantiation). Шаблонные сущности (шаблоны функций и функции-члены шаблонных классов) можно не только определять в глубине единиц трансляции, но также и экспортировать из DLL.
Суть явного инстанцирования шаблонов можно объяснить на интуитивном уровне. Вот эти строки в твоем примере, это аналог явного инстанцирования: