singlepost

шаблоны в С++ << На главную или назад  

существуют ли ограничения на вложенность шаблонов в С++и есть смысл вобще реализовывать эту вложенность?
не смог найти инфу, если есть возможность дайте плз ссылку на статьи по этой теме

19 ответов в теме “шаблоны в С++”

  1. 19
    Павел Потапов ответил:

    #17
    Все-таки я не согласен со сравнением метаинформации и шаблонов :) Это ортогональные вещи. Метаинформацию используют для получения информации о классах и прочем в ран-тайм. А шаблоны используют для генерации однотипного кода. Даже в случае с умными указателями шаблоны нужны для выполнения каких-то однотипных действий, например, подсчета ссылок (тем или иным образом).

    #15
    В свое время я трудился над этим продуктом
    //www.orgplus.com/products/orgplus-professional/
    STL там точно использовался. Как минимум мною ;)

  2. 18
    Александр Lert ответил:

    Артём Шалхаков:

    Нет, вы вроде всё правильно сказали насчёт специального (ad-hoc) полиморфизма. По крайней мере, я то же под ним понимаю :)
    То что специальный полиморфизм одно и то же с параметрическим, я как раз и говорил именно в смысле, что ВНЕШНЕ для программиста это одно и то же.
    В общем, все вроде ОК, все друг друга поняли :)

    А за статью спасибо, почитаю.

  3. 17
    Артём Шалхаков ответил:

    2 Александр Бич

    > любой стандарт весьма туманен

    Так оно и есть, увы.

    > А, в случае MS VS тут вообще швах.

    Это относится ко всем продуктам MS. :)

    > Насчёт романа не понял. Может, конкретно напишете, что туманного в шаблонах?

    Нашел тут статейку, в которой, собственно, выражается та же мысль, которую я тут пытаюсь протолкнуть: //www.kuro5hin.org/story/2003/5/26/22429/7674 (там еще и обсуждение неплохое).

    > параметрический полиморфизм не отличается от специального полиморфизма …

    Кажись, я неправильно выразился. В пейпере "Understading the notion of types in programming languages" дана хорошая диаграмма, и там был как раз таки пример. Мне тут в студии говорят, что специальный полиморфизм это параметрический плюс контекст. Память моя память. :)

    В общем, я хотел примерно вот это сказать (пишу кодом, если где ошибки, то сразу прошу прощения, уж очень давно С++ не трогал):

    // список
    template <typename a>
    class my_reinvented_list {
    a value;
    my_reinvented_list<a> *tail;
    }
    // функция над списком
    template <typename a>
    int length(my_reinvented_list<a> *xs) {
    return (xs == NULL)? 0 :
    1 + length(xs->tail);
    }

    Функция length тут одна, и какую T не подставляй*, она будет работать одинаково для любых типов. А вот эти функции имеют одинаковое имя, но разную реализацию (в зависимости от типов параметров):

    int sum(int x, int y) { return x + y; }
    float sum(float x, float y) { return x + y; }

    * для Си++ это не сильно верно, а вот для Haskell, SML, OCaml, etc. — выполняется

    Вот о втором случае я и говорил как о "специальном" (ad-hoc) полиморфизме. Исправления приветствуются.

    > а по сути он превращает параметрический полиморфизм в специальный, но этого никто не замечает, и от этого не страдает

    В любом случае, это деталь реализации. :) Мы тут о высоком. ^_^

  4. 16
    Александр Lert ответил:

    Спасибо за ценные комментарии.

    Артём Шалхаков:

    С Java я действительно загнул, т.е. забыл про type erasure. (Ну, Java не основной мой язык :) ).
    Лучше бы я привел пример с .NET, где начиная с 2.0 появились истинные generics, поддерживающиеся на уровне CLR, конечно, без совместимости с 1.0. Правда, там они выполняют не только уменьшение количества приведений типов, но и увеличение производительности, так как уменьшают количество необходимых boxing/unboxing.

    Насчёт стандарта C++: по-моему, любой стандарт весьма туманен :) , а реализаторы весьма творческие люди, любящие сделать по-своему :)
    А, в случае MS VS тут вообще швах. Более-менее соответственно стандарту он стал компилировать, по-моему, только с 2005 версии. Взять хотя бы забитый пример про область действия переменных, объявленных в заголовке цикла: for(int i=0; … ) { … }. Я видел 3 варианта реализации этой вещи в разных компиляторах, хотя тут то что туманного? :)

    Насчёт романа не понял. Может, конкретно напишете, что туманного в шаблонах?

    Павел Scavenger Потапов:

    Поздравляю, что решили, хоть задача и несложная. У меня еще был прикольный пример на эту фишку, только я его не могу вспомнить. Может, потом вспомню и напишу.

    Да, шаблоны не заменят метаинформации и reflection. Но по-моему, сравнение шаблонов и метаинформации весьма корректно. Понятно, что в случае с шаблонами все известно на этапе компиляции. Но вообще-то это только увеличивает производительность.
    Артём Шалхаков:
    С точки зрения "невъедливого" программиста, параметрический полиморфизм не отличается от специального полиморфизма, кроме случаев, когда реально необходима рефлексия, то есть об исходном типе неизвестно вообще ничего.
    При компиляции .NET сборки в промежуточном коде все generics сохраняются как с параметрическим полиморфизмом. Но, на сколько я понимаю, JIT-компилятор .NET при компиляции generics компилирует несколько их версий на лету, в соответствии с generic параметрами, что только увеличивает производительность, а по сути он превращает параметрический полиморфизм в специальный, но этого никто не замечает, и от этого не страдает. :) Если я не прав с JIT, поправьте.

  5. 15
    Роман Белоус ответил:

    2Артём:
    > Ссылки на такие проекты в студию. Кстати, замечаю, что STL часто не используют по разным причинам (типа, религиозным ^_^).

    А что, ты полагаешь, что они не используются? У меня ощущение, что это тоже самое, что подвергать сомнению широкое использование Hibernate в Java, хотя лично я не знаю ни одного конкретного проекта, где он бы использовался =) Я в С++ сообственно не рублю, поэтому конкретных проектов также не знаю, но точно знаю, что, например,в маленькой фирме //www.auditech.ru/ используется boost в каких-то проектах.

  6. 14
    Артём Шалхаков ответил:

    2 Александр Дзюба
    > Windows XP

    Пруф или не было.

    2 Павел Потапов
    > Почти любой проект, где используются STL, boost

    Ссылки на такие проекты в студию. Кстати, замечаю, что STL часто не используют по разным причинам (типа, религиозным ^_^).

    2 Александр Бич

    >Формализованнейшее описание шаблонов есть собственно в стандарте C++

    Больше похоже на роман какой-то. :) Отталкиваться нужно от теории множеств или чего другого, более специфичного.

    > Правда ранние версии MS VS (вплоть по-моему до 2003) плохо компилировали шаблонные извращения

    Стандарт С++ принят в 98-м. Это, получается, что шаблоны асиливали ПЯТЬ лет. Как бы подчеркивает, что в стандарте все туманно.

    > различные обобщенные контейнеры (vector и т.д.), обобщенные алгоритмы и вещи типа "умные указатели" (auto_ptr и т.д.)

    Чтобы получить параметрический полиморфизм, нужно допиливать систему типов. А потом можно и классы типов организовать. :)

    > В Java шаблоны тоже сделали, хотя там они вообще нужны только для того, чтобы уменьшить количество приведений типов.

    В Java используется type erasure, и generics нужны только для того, чтобы чуть обезопасить приведение типов (а не уменьшить их количество). ^_^

  7. 13
    Павел Потапов ответил:

    #13 потому, что он выводит 3 шаблона по-очереди:
    Fact<400>
    Fact<800>
    Fact<1200>
    В каждом случае вложенность шаблонов около 400. Компилятор использует ранее определенные шаблоны, дабы не париться с повторным их вычислением…

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

    #9
    Почти любой проект, где используются STL, boost или хотя бы ATL с CString и/или CComPtr ;) Почти все умные указатели, которые я видел, использовали шаблоны.

  8. 12
    Александр Lert ответил:

    Если кому интересна тема про шаблоны, еще тест. Возмем код из поста #6, и изменим main так:

    void main()
    {
    int a400=Fact<400>::value;
    int a800=Fact<800>::value;
    int a1200=Fact<1200>::value;
    . . . // и т.д. с шагом в 400
    int a10000=Fact<10000>::value;

    cout<<a10000;
    }

    Этот код компилируется и в GNU C++, и в MS VS (правда уйма warning'ов) хотя вроде строк в нем еще больше, чем в посте #6. Почему код компилируется, кто первый объяснит ? ;) У меня препод один долго думал!

  9. 11
    Артур Терменжи ответил:

    #7
    Александр quyse Бич
    спасиб большой, оч интересные тесты

  10. 10
    Александр Дзюба ответил:

    >>это, назовите несколько крупных проектов, где широко используются шаблоны.

    Windows XP :)

  11. 9
    Александр Lert ответил:

    Артём Шалхаков:

    Формализованнейшее описание шаблонов есть собственно в стандарте C++:
    //www.kuzbass.ru/docs/isocpp/template.html
    или
    ftp://ftp.research.att.com/pub/c++std/WP/CD2

    Насчет туманности – это зря. Там всё четко, только разобраться надо. Правда ранние версии MS VS (вплоть по-моему до 2003) плохо компилировали шаблонные извращения, путались и несли бред по поводу якобы ошибок, и некоторые могли сделать вывод, что шаблоны – это странные и туманные конструкции. Но сейчас на большей части современных компиляторов все компилируется правильно.

    Проектов с шаблонами не знаю, кроме своих :) Действительно, по-видимому, общественность не торопится широко использовать шаблоны. Может, в них просто мало людей разобралось …

    Самое полезное, что можно сделать с шаблонами, по моему мнению, уже сделано в Standard Template Library: различные обобщенные контейнеры (vector и т.д.), обобщенные алгоритмы и вещи типа "умные указатели" (auto_ptr и т.д.), облегчающие работу с памятью, учитывающие ссылки и т.д. Например, очень эффектно можно сделать имитацию виртуальной памяти (полезно для дизассемблеров и эмуляторов), чтобы работа с ней ничем не отличалась от обычной памяти (определить "умный" указатель), автосохраняемая память (это у меня только уйма идей по шаблонам что ли?).

    По сути, смысл шаблонов в том, чтобы в полуавтоматическом режиме работать с метаинформацией о типах, генерируемой компилятором. И хотя возможности шаблонов ограничены, их можно рассматривать как дешевый (в смысле производительности) заменитель возможностей языков (платформ) со встроенной поддержкой метаинформации о типах (Managed C++, C#, Java).
    Хотя, в любом случае, шаблоны – очень удобная вещь. В Java шаблоны тоже сделали, хотя там они вообще нужны только для того, чтобы уменьшить количество приведений типов.

  12. 8
    Артём Шалхаков ответил:

    2 Александр Бич

    Если бы у компилятора С++ была бы возможность определить, что какая-то функция f не имеет побочных эффектов, можно было бы замутить интерпретацию функции во время компиляции (в принципе, это можно сделать для функций с побочными эффектами, но мне так не нравится :) ) А еще это можно было бы сделать автоматически, без участия программиста.

    Вопрос: зачем было делать внутри языка еще один язык с туманными правилами? Реквестирую какое-нибудь формальное описалово этих самых шаблонов. Под ними наверняка есть какой-то теоретический базис.

    И это, назовите несколько крупных проектов, где широко используются шаблоны. В Мозилле, например, их нет.

  13. 7
    Павел Потапов ответил:

    По стандарту уровень вложенности шаблонов зависит от компилятора. Уровни вложенности для GCC и VC++ вы уже посчитали. :)

  14. 6
    Александр Lert ответил:

    Конечно, правильно, что в GNU C++ есть ограничение по вложенности – оно позволяет прекратить компиляцию в случае бесконечной вложенности (например, если забыть определить template<> struct Fact<0> в предыдущем посте, то он будет компилировать классы от Fact<10> до Fact<-0×80000000>). А теперь, кто рискнет скомпилировать следующее:
    template <class T1, class T2>
    struct A
    {
    A<A<T1, T2>, T2> a1;
    A<T1, A<T1, T2> > a2;
    };
    A<int, int> a;//глобальная переменная, заставляющая выполнить компиляцию

    Смотрим: компилятор сначала компилирует класс A<int, int>. Затем A<A<int, int>, int> и A<int, A<int, int> >. Затем A<A<A<int, int>, int>, int>, A<A<int, int>, A<A<int, int>, int> >, … . На каждом классе идет разветвление на 2. GNU C++ остановится только при достижении вложенности в 500. Посчитайте, сколько классов он скомпилирует?
    Также, так как компилятор выдаёт на каждый класс, для которого он начинал компиляцию, сообщение, то компиляция данной программы порождает огромный вывод в 2^500 (2 в степени 500) строк! Да, он действительно выведет 2^500 строк (если дать ему время :) ). Если вывод компилятора перенаправляется в файл, как обычно и делается, то дисковое пространство расходуется очень быстро.
    Интересно, что MS VS 2008 также падает при попытке компиляции этого примера, что спасает его от зависания :)

  15. 5
    Александр Lert ответил:

    Это весьма интересная тема
    Если под вложенностью подразумевается то, сколько раз можно вкладывать Type<Type<Type<…> > >, то современные компиляторы, по-видимому, с этим проблем не имеют.
    Гораздо интереснее вложенность компиляции, т.е. сколько шаблонов компилятор может скомпилировать рекурсивно. По этому вопросу несложно провести соответствующие эксперименты.
    Простая программа, вычисляющая факториал на этапе компиляции (извращение, конечно :) но в интересах науки):
    template <int n> struct Fact
    {
    static const int value=n*Fact<n-1>::value;
    };
    template <> struct Fact<0>
    {
    static const int value=1;
    };

    void main()
    {
    cout<<Fact<10>::value;
    }
    Вывод: 3628800 – правильно. Эта программа компилируется как GNU C++, так и MS VS 2008. Но если вместо 10 поставить 10000, то выясняется, что в GNU C++ по умолчанию стоит ограничение в 500, и он выдаёт около 500 строк – ошибок компиляции (на каждый класс от Fact<10000> до Fact<10000-499>, проверьте, интересно). MS VS в этом случае также выдаёт около 500 строк, а затем с грохотом падает (по видимому, от переполнения стека :) не подумали в MS о таком).

  16. 4
    Алексей Близнюк ответил:

    можно рекурсивно инстанциировать шаблон. MS Visual Studio при на каком-то этапе выдает ошибку компиляции.

  17. 3
    Александр Дзюба ответил:

    шаблоны ОФИГЕННО нужная штука, правда не въехал про вложенность :)

  18. 2
    Кирилл Быков ответил:

    Брось, Артём, шаблоны — нужная штука.

  19. 1
    Артём Шалхаков ответил:

    А мне интересно, какую траву курили в комитете, чтобы выдумать шаблоны.

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.