Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Статический экземпляр класса в шаблоне 
:(
    Опции темы
Tiarwe
Дата 1.1.2014, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 24.8.2011

Репутация: нет
Всего: нет



Здравствуйте!
Есть шаблонный класс. Внутри у него вложенный класс. Требуется создать внутри статический член этого вложенного класса.

Пытался так:
Код

template<class T>
class A
{
public:
    class B
    {
    public:
    };

    static B    mB;
};

template<class T>
A<T>::B A<T>::B::mB;


Но при компиляции ошибки:
Цитата

Warning    1    warning C4346: 'A<T>::B' : dependent name is not a type
Error    2    error C2143: syntax error : missing ';' before 'A<T>::B::mB'    
Error    3    error C1903: unable to recover from previous error(s); stopping compilation


Как можно создать статический экземпляр вложенного в шаблон класса? И возможно ли это вообще?

PM MAIL   Вверх
mabrarov
Дата 1.1.2014, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 100
Регистрация: 12.1.2011
Где: Казань

Репутация: 8
Всего: 9



Цитата(Tiarwe @ 1.1.2014,  17:14)
Warning    1    warning C4346: 'A<T>::B' : dependent name is not a type
Error    2    error C2143: syntax error : missing ';' before 'A<T>::B::mB'    
Error    3    error C1903: unable to recover from previous error(s); stopping compilation

Use typename, Luke!
Код
template<typename T>
class A
{
public:
  class B
  {
  public:
  };

  static B mB;
};

template<typename T>
typename A<T>::B A<T>::mB;

И это еще не создание статического члена, а лишь описание того, как он должен создаваться при специализации шаблонного класса A.
PM MAIL WWW Skype   Вверх
akizelokro
Дата 2.1.2014, 19:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Код

  static B mB;

ты ещё даже класс B не объявил, а уже используешь в объявлении. как я понял. Как я понимаю, С++ уже зашивается 9в силу ряда причин на таких примерах), да и логичней было бы в любом случае экземпляр класса B вынести хотя бы в класс A


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
Lukkoye
Дата 3.1.2014, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 23.3.2013

Репутация: 1
Всего: 1



Цитата(akizelokro @  2.1.2014,  19:35 Найти цитируемый пост)
ты ещё даже класс B не объявил, а уже используешь в объявлении. как я понял. Как я понимаю, С++ уже зашивается 9в силу ряда причин на таких примерах), да и логичней было бы в любом случае экземпляр класса B вынести хотя бы в класс A 


Не верно. Класс B уже известен.
Ошибка была в синтаксисе. Правильный ответ во втором сообщении этой темы.
PM MAIL   Вверх
akizelokro
Дата 6.1.2014, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата(Lukkoye @  3.1.2014,  18:52 Найти цитируемый пост)
Правильный ответ во втором сообщении этой темы. 


Угу. Но я, походу, ещё никак С++ 11 не освою.  smile 



--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
vinter
Дата 6.1.2014, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(akizelokro @  6.1.2014,  17:31 Найти цитируемый пост)
Угу. Но я, походу, ещё никак С++ 11 не освою.

Здесь нет кода, который требует функционал C++11


--------------------
Мой блог
PM MAIL WWW   Вверх
akizelokro
Дата 6.1.2014, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата(vinter @  6.1.2014,  17:44 Найти цитируемый пост)
Здесь нет кода, который требует функционал C++11 


Есть. Я даже подноготную рассмотрел 6-летней давности для применения typename и class. Начиная от исторических ссылок, вариантов применения в различных компляторов и тра-ля-ля ещё что-то там. Вообще сам typename и характер его применения сформировался именно на подходе к С++ 11. Я даже с примерами рассмотрел (я не тот чингачгук, который два раза на одни грабли наступает).

Вообще, я так понял, что вообще желательно typename пихать в код куда надо и, куда, как, казалось бы, не надо. И маложелательно употреблять class (вроде новомодная тенденция? )




--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
Lukkoye
Дата 6.1.2014, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 23.3.2013

Репутация: 1
Всего: 1



Цитата(akizelokro @  6.1.2014,  20:37 Найти цитируемый пост)
Вообще, я так понял, что вообще желательно typename пихать в код куда надо и, куда, как, казалось бы, не надо. И маложелательно употреблять class (вроде новомодная тенденция? )


Можно так:
http://codepad.org/x2LKMHsw


Код

template<class T>struct A
{
  struct B {};
  static B mB;
};
template<class T> struct A<T>::B A<T>::mB;

int main()
{
   A<int> a;
}



По поводу использования typename неплохо написала Елена Сагалева в своем блоге:
http://alenacpp.blogspot.ru/2006/08/typename.html


От себя я могу лишь добавить: на моей практике наиболее частое использование typename  - это typedef в шаблонах, при метапрограммировании.

Я покажу вам простейший пример:

http://rextester.com/CEC63398

Код

#include<typeinfo>
#include<iostream>
using namespace std;

//---------вернет true, если типы одинаковые------//
template <typename T, typename U> struct IsEqual { enum { value = false }; };
template <typename T> struct IsEqual<T,T> { enum { value = true }; };
//------------------------------------------------//

//--------------------если T равно U, то результат будет D, а иначе - G------------//
template<class T, class U, class D, class G> struct TSelectIF  { typedef G Result_t; };
template<class T, class D, class G>  struct TSelectIF<T,T,D,G> { typedef D Result_t; };
//------------------------------------------------//

struct SEmpty{};

template<class T>struct Test
{
    // --- мы используем ключевое слово 'typename'
    // --- что бы сообщить компилятору, что Result_t - это имя типа, 
    // --- которое зависит от параметров шаблона TSelectIF
    typedef typename TSelectIF<T, void, SEmpty,T>::Result_t Type;
};

int main()
{
    typedef Test<void>::Type Type1;
    cout<<"class name: "<<typeid(Type1).name()<<endl;
    
    const bool is_sempty1 = IsEqual<Type1, SEmpty>::value;
    cout<< "is sempty? "<< ((is_sempty1)? "yes":"not")<<endl;
    
    //------//    
    
    typedef Test<int>::Type Type2;
    cout<<"class name: "<<typeid(Type2).name()<<endl;
    
    const bool is_sempty2 = IsEqual<Type2, SEmpty>::value;
    cout<< "is sempty? "<< ((is_sempty2)? "yes":"not")<<endl;
}



Здесь, в зависимости от того, чем будет Т в шаблоне:
template<class T>struct Test

Его внутренний:
typedef typename TSelectIF<T, void, SEmpty,T>::Result_t Type;

Будет принимать значение либо SEmpty, либо T

Но известно это станет лишь в момент инстанцирования шаблона, а до этого момента, компилятору нужно что-то сделать с этой записью: понять, чему именно сопоставляется имя типа Type:

typedef  ...что-то-непонятное... Type;  

Мы указываем typename, давая понять компилятору, что там - некий тип данных, который зависит от параметров родительского шаблона, и поэтому станет известен позже - в момент инстанцирования.

Это сообщение отредактировал(а) Lukkoye - 6.1.2014, 22:33
PM MAIL   Вверх
akizelokro
Дата 7.1.2014, 07:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Есть ещё неплохая статья на хабре.
И, не помню уже где, но идёт предположение, что некоторые компиляторы требуют typename даже с некоторой избыточностью. И вами не указаны примеры, навроде "классического", как я понимаю:

template <typename T> some_function()
{
  ...
  typename T::iterator it; // iterator может быть stl-ским итератором, а может быть просто членом класса T
  ...
  // простые примеры с разночтениями списков инициализаций и определениями пустых функций
}
одними typedef применение typename не ограничивается. Просто мы сейчас рассматриваем достаточно простые примеры с шаблонами, например, функций в одну строку.

В MSVS этот пример не компилится совсем.
Код

template<class T>struct A
{
  struct B {}; // непонятно, что будет в зависимости от компилятора. объявление или инициализация?
  static B mB;
};
template<class T> struct A<T>::B A<T>::mB;


И этот не компилится

Код

template<class T>struct A
{
  struct B {};
  static B mB;
};
template<class T> struct A<T>::B A<T>::mB;


А этот вызывает внутренную ошибку компилятора.
Код

template<class T>
struct A
{
public:
    struct B {
//    public:
    };

  static struct B mB;
 
};
template<class T> typename struct A<T>::B A<T>::mB;

Думаю, что struct из-за двоякости их определения (можно указывать struct или нет в ряде выражений, или так мне только кажется), несут известный риск при применении


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
vinter
Дата 7.1.2014, 08:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(akizelokro @  6.1.2014,  21:37 Найти цитируемый пост)
Есть. Я даже подноготную рассмотрел 6-летней давности для применения typename и class. Начиная от исторических ссылок, вариантов применения в различных компляторов и тра-ля-ля ещё что-то там. Вообще сам typename и характер его применения сформировался именно на подходе к С++ 11. Я даже с примерами рассмотрел (я не тот чингачгук, который два раза на одни грабли наступает).

я не знаю о чём ты говоришь, никаких изменений касающихся ключевого слова typename в C++11 нет.

Цитата(akizelokro @  7.1.2014,  08:13 Найти цитируемый пост)
Есть ещё неплохая статья на хабре.И, не помню уже где, но идёт предположение, что некоторые компиляторы требуют typename даже с некоторой избыточностью. И вами не указаны примеры, навроде "классического", как я понимаю:

На заборе тоже написано. Это видимо те же "предполагатели", что к гадалкам ходят.
Цитата(akizelokro @  7.1.2014,  08:13 Найти цитируемый пост)
В MSVS этот пример не компилится совсем.

Потому, что это некорректный C++ код. Как он должен компилироваться?
Код

template<class T>
struct A
{
    struct B {};
    static B mB;
};

template<class T> typename A<T>::B A<T>::mB;

Цитата(akizelokro @  7.1.2014,  08:13 Найти цитируемый пост)
Думаю, что struct из-за двоякости их определения (можно указывать struct или нет в ряде выражений, или так мне только кажется), несут известный риск при применении

У тебя каша в голове, struct используется только при декларации\определении структуры. Больше его совать никуда не стоит - оно там быть не должно.



--------------------
Мой блог
PM MAIL WWW   Вверх
vinter
Дата 7.1.2014, 08:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Посмотри эту книгу, там есть всё, что нужно знать про шаблоны. Правда без новшеств, типа variadic templates, но книга всё равно должна помочь в понимании.

Это сообщение отредактировал(а) vinter - 7.1.2014, 08:57


--------------------
Мой блог
PM MAIL WWW   Вверх
akizelokro
Дата 7.1.2014, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата(vinter @  7.1.2014,  08:33 Найти цитируемый пост)
Потому, что это некорректный C++ код. Как он должен компилироваться?


Не компилится другой пример, а указанный вами как раз и компилится.

Цитата(vinter @  7.1.2014,  08:33 Найти цитируемый пост)
У тебя каша в голове, struct используется только при декларации\определении структуры. Больше его совать никуда не стоит - оно там быть не должно.


Насколько я понял (могу и ошибаться), в C++ 14 будет возможна и инициализация вида

struct B { int x = 5, int y = 3; };

или в куче материала я просто увидел такую хотелку, уже прямо так сразу и не вспомнить.

Цитата(vinter @  7.1.2014,  08:33 Найти цитируемый пост)
У тебя каша в голове, struct используется только при декларации\определении структуры. Больше его совать никуда не стоит - оно там быть не должно.
.

Ну, ещё, отбросив предыдущий, возможно некорректный пример, статические постоянные члены struct могут проинициализированы при декларации/определении. Также инициализацию списком подцепляют и к декларации. Также, осталось и, кажись наследство С в виде 

Код

struct B c;


Видел и такие конструкции. А всё что не запрещено, - разрешено.

Но в голове каша реальная вырисовывается. Потому ещё не все, как я понял, компиляторы, реализовали полностью нововведения из С++ 11, а тут ещё на подходе С++ 14, который тоже начнут реализовывать в непонятной последовательности пунктов. 
А за ссылку - спасибо.



--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
vinter
Дата 7.1.2014, 09:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(akizelokro @  7.1.2014,  10:29 Найти цитируемый пост)
Насколько я понял (могу и ошибаться), в C++ 14 будет возможна и инициализация вида

она уже есть(в C++11). Но у тебя же код, который явно означает определение структуры:
Код

struct B {};

Чтобы это стало инициализацией это должно выглядеть так:
Код

struct B b{};

Цитата(akizelokro @  7.1.2014,  10:29 Найти цитируемый пост)
Потому ещё не все, как я понял, компиляторы, реализовали полностью нововведения из С++ 11, а тут ещё на подходе С++ 14, который тоже начнут реализовывать в непонятной последовательности пунктов. 

В clang полностью реализован C++14


--------------------
Мой блог
PM MAIL WWW   Вверх
akizelokro
Дата 7.1.2014, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Крокодил
**


Профиль
Группа: Участник
Сообщений: 761
Регистрация: 30.7.2007

Репутация: 1
Всего: 5



Цитата(vinter @  7.1.2014,  09:35 Найти цитируемый пост)
В clang полностью реализован C++14 


Каша намечается забавная! 
Всё-таки в ООП схеме
Код


class CPlusPlus : class C
{
  ...
}


наследование от С - более азартная вещь, чем 100%-ООП парадигма  smile 


--------------------
a = a + b; b = a - b; a = a - b;
PM MAIL   Вверх
bsa
Дата 7.1.2014, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(Tiarwe @  1.1.2014,  18:14 Найти цитируемый пост)
Требуется создать внутри статический член этого вложенного класса.

Напрямую сделать это нельзя. Можно сделать статический метод, который содержит объявление статической переменной и возвращает ссылку на нее.
Код
template<class T>
class A
{
public:
    class B
    {
    public:
    };

    static B& getB() { static B    mB; return mB; }
};

PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0599 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.