| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > Статический экземпляр класса в шаблоне |
| Автор: Tiarwe 1.1.2014, 17:14 | ||||
| Здравствуйте! Есть шаблонный класс. Внутри у него вложенный класс. Требуется создать внутри статический член этого вложенного класса. Пытался так:
Но при компиляции ошибки:
Как можно создать статический экземпляр вложенного в шаблон класса? И возможно ли это вообще? |
| Автор: mabrarov 1.1.2014, 19:17 | ||||
Use typename, Luke!
И это еще не создание статического члена, а лишь описание того, как он должен создаваться при специализации шаблонного класса A. |
| Автор: akizelokro 2.1.2014, 19:35 | ||
ты ещё даже класс B не объявил, а уже используешь в объявлении. как я понял. Как я понимаю, С++ уже зашивается 9в силу ряда причин на таких примерах), да и логичней было бы в любом случае экземпляр класса B вынести хотя бы в класс A |
| Автор: akizelokro 6.1.2014, 16:31 |
Угу. Но я, походу, ещё никак С++ 11 не освою. |
| Автор: vinter 6.1.2014, 17:44 |
Здесь нет кода, который требует функционал C++11 |
| Автор: akizelokro 6.1.2014, 20:37 |
Есть. Я даже подноготную рассмотрел 6-летней давности для применения typename и class. Начиная от исторических ссылок, вариантов применения в различных компляторов и тра-ля-ля ещё что-то там. Вообще сам typename и характер его применения сформировался именно на подходе к С++ 11. Я даже с примерами рассмотрел (я не тот чингачгук, который два раза на одни грабли наступает). Вообще, я так понял, что вообще желательно typename пихать в код куда надо и, куда, как, казалось бы, не надо. И маложелательно употреблять class (вроде новомодная тенденция? ) |
| Автор: Lukkoye 6.1.2014, 22:27 | ||||||
Можно так: http://codepad.org/x2LKMHsw
По поводу использования typename неплохо написала Елена Сагалева в своем блоге: http://alenacpp.blogspot.ru/2006/08/typename.html От себя я могу лишь добавить: на моей практике наиболее частое использование typename - это typedef в шаблонах, при метапрограммировании. Я покажу вам простейший пример: http://rextester.com/CEC63398
Здесь, в зависимости от того, чем будет Т в шаблоне: template<class T>struct Test Его внутренний: typedef typename TSelectIF<T, void, SEmpty,T>::Result_t Type; Будет принимать значение либо SEmpty, либо T Но известно это станет лишь в момент инстанцирования шаблона, а до этого момента, компилятору нужно что-то сделать с этой записью: понять, чему именно сопоставляется имя типа Type: typedef ...что-то-непонятное... Type; Мы указываем typename, давая понять компилятору, что там - некий тип данных, который зависит от параметров родительского шаблона, и поэтому станет известен позже - в момент инстанцирования. |
| Автор: akizelokro 7.1.2014, 07:13 | ||||||
| Есть ещё неплохая статья на хабре. И, не помню уже где, но идёт предположение, что некоторые компиляторы требуют typename даже с некоторой избыточностью. И вами не указаны примеры, навроде "классического", как я понимаю: template <typename T> some_function() { ... typename T::iterator it; // iterator может быть stl-ским итератором, а может быть просто членом класса T ... // простые примеры с разночтениями списков инициализаций и определениями пустых функций } одними typedef применение typename не ограничивается. Просто мы сейчас рассматриваем достаточно простые примеры с шаблонами, например, функций в одну строку. В MSVS этот пример не компилится совсем.
И этот не компилится
А этот вызывает внутренную ошибку компилятора.
Думаю, что struct из-за двоякости их определения (можно указывать struct или нет в ряде выражений, или так мне только кажется), несут известный риск при применении |
| Автор: vinter 7.1.2014, 08:33 | ||||||||
я не знаю о чём ты говоришь, никаких изменений касающихся ключевого слова typename в C++11 нет.
На заборе тоже написано. Это видимо те же "предполагатели", что к гадалкам ходят. Потому, что это некорректный C++ код. Как он должен компилироваться?
У тебя каша в голове, struct используется только при декларации\определении структуры. Больше его совать никуда не стоит - оно там быть не должно. |
| Автор: vinter 7.1.2014, 08:56 |
| Посмотри эту http://www.ozon.ru/context/detail/id/3960662/, там есть всё, что нужно знать про шаблоны. Правда без новшеств, типа variadic templates, но книга всё равно должна помочь в понимании. |
| Автор: akizelokro 7.1.2014, 09:29 | ||||||||
Не компилится другой пример, а указанный вами как раз и компилится.
Насколько я понял (могу и ошибаться), в C++ 14 будет возможна и инициализация вида struct B { int x = 5, int y = 3; }; или в куче материала я просто увидел такую хотелку, уже прямо так сразу и не вспомнить.
Ну, ещё, отбросив предыдущий, возможно некорректный пример, статические постоянные члены struct могут проинициализированы при декларации/определении. Также инициализацию списком подцепляют и к декларации. Также, осталось и, кажись наследство С в виде
Видел и такие конструкции. А всё что не запрещено, - разрешено. Но в голове каша реальная вырисовывается. Потому ещё не все, как я понял, компиляторы, реализовали полностью нововведения из С++ 11, а тут ещё на подходе С++ 14, который тоже начнут реализовывать в непонятной последовательности пунктов. А за ссылку - спасибо. |
| Автор: vinter 7.1.2014, 09:35 | ||||||||
она уже есть(в C++11). Но у тебя же код, который явно означает определение структуры:
Чтобы это стало инициализацией это должно выглядеть так:
В clang полностью реализован C++14 |
| Автор: akizelokro 7.1.2014, 12:33 | ||
Каша намечается забавная! Всё-таки в ООП схеме
наследование от С - более азартная вещь, чем 100%-ООП парадигма |
| Автор: bsa 7.1.2014, 12:49 | ||
Напрямую сделать это нельзя. Можно сделать статический метод, который содержит объявление статической переменной и возвращает ссылку на нее.
|
| Автор: Lukkoye 7.1.2014, 13:21 | ||
Я на самом деле так же делаю, по двум причинам: 1. Код проще написать, и проще потом прочитать. 2. Независимость от порядка инициализации единиц трансляции. Однако, довольно странно читать "напрямую сделать это нельзя" , когда незадолго до вас уже указали способ, "как это сделать можно". |
| Автор: vinter 7.1.2014, 13:22 |
Можно, и самый первый ответ в этой теме является верным. |
| Автор: akizelokro 7.1.2014, 14:05 | ||
Вообще-то, это последняя версия класса Singleton class Singleton { public: static Singleton & getInstance() { static singleton s; return s; } private: // constructors and destructors } Добавлено @ 14:10 Здесь вообще конфронтация. Изначальная формулировка задачи "Требуется создать внутри статический член этого вложенного класса.". Дырбулышург. Делайте вложенным классом подобие Singleton, для разнообразия попробуйте его как static class И очень многое получите. А вообще, мне просто не было надобности работать с С++ и с шаблонами, тоже мне задача, я работал на C++ как с чистым Cшником. Поэтому не было так весело! |
| Автор: akizelokro 7.1.2014, 14:22 |
| Вообще, щас пики забивают на thread-safe экземпляр класса Singleton (спорят, какая реализация будет потокобезопасной). Я так спьяну глянул, и понял, что будет последняя версия (которую я зачтил), и набросок которой привёл bsa/ Остальные пусть ждут стандартной версии компирела. Меня же больше в примере с singleton заинтересовали не откровения кучи прогеров и не приблуды, которыми они его в разных версиях компилеров пытались "расшифровать", а N-тоны (Double-tone, Three-tone and so on) |
| Автор: bsa 9.1.2014, 10:52 | ||
akizelokro, мой пример - это не зачаток "singleton". Просто в singleton используется тот же механизм. |
| Автор: vinter 9.1.2014, 14:15 | ||||
В данном случае, задача линкера заткнуться и свести все эти инстанциации в одну. Тут тот же случай, что и с функциями. Тут нет явной инстанциации в заголовке, а значить ODR не нарушается. Добавлено @ 14:19
|
| Автор: Lukkoye 10.1.2014, 19:58 | ||
Нет, не будет. Кстати, это свойство шаблонов используют для проворачивания трюка "объявить и туловище и реализацию свободной функции в хэдэре так, что бы не иметь проблем с линкером". Хотя лично я, для проворачивания аналогичного трюка использую статический метод обычного класса. Если объявить и определить статический метод прямо в декларации класса, то проблем с линкером так же не будет. |
| Автор: mabrarov 10.1.2014, 20:37 | ||||||
Коллеги, не "ткнете" ли меня (как автора первого ответа) туда, где сказано, что typename в данном случае имеет какое-то отношение к C++11. Думаю, разница м/у typename и class при использовании в шаблонах есть только в http://software.intel.com/ru-ru/blogs/2012/01/03/typename-class-2.
Там, где я подразумеваю тип (например, в шаблонах), я пишу typename, а не class. Так мне понятнее и логичнее (тип же не ограничивается классом). Тенденция, думается, в лучших традициях C++03 Добавлено через 8 минут и 15 секунд
Не проще ли inline-функции? Хотя в их случае компилятор волен http://habrahabr.ru/company/abbyy/blog/108166/ (а он может зависеть от препроцессора), что как бы намекает на дополнительную аккуратность при использовании inline-функций... |
| Автор: baldina 10.1.2014, 22:02 | ||
не-а. потому что это не так. |
| Автор: Lukkoye 11.1.2014, 03:18 | ||
Нет, не проще. Потому что inline или нет - решает компилятор. Необходимость следить за этим вручную делает этот подход несопоставимо более сложным, чем простая и узнаваемая всеми программистами статическая функция член, которая не отягощает интеллект дополнительными думками ещё и о линкере. |
| Автор: nonaot 14.1.2014, 22:53 |
Модератор: Сообщение скрыто. |