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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> проблема компиляции шаблонных классов 
V
    Опции темы
bsa
Дата 26.10.2006, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Пример, иллюстрирующий проблему:
Код
template <class T>
class Container {
    unsigned pos;
public:
    Container(unsigned p): pos(p) {}
    Container(const Container& value) : pos(value.pos) {}
};

template <class T>
class Segment {
    unsigned pos;
public:
    typedef Container<T> Container;
    Segment(unsigned p) : pos(p) {}
    Container operator[](unsigned index) {
        return Container(pos + index*sizeof(T));
    }
};

template<class T>
struct SomeClass {
    struct SomeStruct{
        int s;
        int a;
    };
    typedef Segment<SomeStruct> SegS;

    SomeClass() {
        SegS::Container s(0);
    }
};

main() {
    SomeClass<int> s;
    return 0;
}
При компиляции g++ ругается:
Цитата
aaa.cpp: In constructor ‘SomeClass<T>::SomeClass()’:
aaa.cpp:29: error: expected `;' before ‘s’
aaa.cpp: In constructor ‘SomeClass<T>::SomeClass() [with T = int]’:
aaa.cpp:36:   instantiated from here
aaa.cpp:29: error: dependent-name ‘Segment<SomeClass<T>::SomeStruct>::Container’ is parsed as a non-type, but instantiation yields a type
aaa.cpp:29: note: say ‘typename Segment<SomeClass<T>::SomeStruct>::Container’ if a type is meant

Виновника нашел - struct SomeStruct. Если ее вынести из SomeClass, то все работает. Но, мне совершенно не нужно выносить эту структуру за пределы класса. И вообще, она у меня приватная. smile
Из подсказки следует, что в строке 29 надо использовать ключевое слово "typename". Попробовал - помогло. Но мне это не нравится, почему компилятор счел Container нетипом (non-type)? И как сделать так, чтобы он считал его типом без использования typename?
PM   Вверх
Daevaorn
Дата 26.10.2006, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(bsa @  26.10.2006,  23:21 Найти цитируемый пост)
Попробовал - помогло. Но мне это не нравится, почему компилятор счел Container нетипом (non-type)? И как сделать так, чтобы он считал его типом без использования typename? 

Это стандарт. Никуда не деться. Компилятор не может быть уверен, что SegS::Container есть всегда тип. Поэтому ему и нужно дополнительное разъяснение.
PM MAIL WWW   Вверх
bsa
Дата 26.10.2006, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



интересно, а с чем он его перепутать может? Больше же вариантов нет!
с другой стороны, почему работает без typename, если вынести определение SomeStruct за пределы класса?
PM   Вверх
Daevaorn
Дата 26.10.2006, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(bsa @  26.10.2006,  23:29 Найти цитируемый пост)
интересно, а с чем он его перепутать может? Больше же вариантов нет!

Можно написать специализацию при которой SegS::Container будет именем переменной.
Цитата(bsa @  26.10.2006,  23:29 Найти цитируемый пост)
с другой стороны, почему работает без typename, если вынести определение SomeStruct за пределы класса? 

Это уже интересней. Надо обратиться к библии. Скорей всего, что-то с резолвингом зависимых имен связано...

Добавлено @ 22:38 
Первое что пришло в голову, это то что SomeStruct ведь тоже при специализции может перестать быть типом...
PM MAIL WWW   Вверх
bsa
Дата 26.10.2006, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(Daevaorn @ 26.10.2006,  22:36)
Можно написать специализацию при которой SegS::Container будет именем переменной.

Это как?!? В качестве специализации указать не тип, а переменную?!?
PM   Вверх
Daevaorn
Дата 26.10.2006, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(bsa @  26.10.2006,  23:51 Найти цитируемый пост)
Это как?!? В качестве специализации указать не тип, а переменную?!? 

да
PM MAIL WWW   Вверх
bsa
Дата 27.10.2006, 00:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



ясно
PM   Вверх
Earnest
Дата 27.10.2006, 07:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Трехэтажные объявления при работе с шаблонами - обычное дело. Спасают только typedef'ы, скажем: 
Код

typedef typename SegS::Container Conteiner; 

Вопрос, почему компилятор то требует typename, то нет, это скорее всего, его личные тараканы. По моему, всегда должен. 


--------------------
...
PM   Вверх
UnrealMan
Дата 27.10.2006, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Earnest @  27.10.2006,  07:29 Найти цитируемый пост)
Вопрос, почему компилятор то требует typename, то нет, это скорее всего, его личные тараканы. По моему, всегда должен.  

Не, тут всё верно. Смотрите: SomeStruct – это не что иное, как SomeClass<T>::SomeStruct, т.е. зависимый от T тип. Стало быть, Segment<SomeStruct> – это также зависимый от T тип. В таком случае для Segment<SomeClass<T>::SomeStruct>::Container по стандарту полагается прописывать typename. Если же мы выносим SomeStruct за пределы шаблонного класса SomeClass, то теперь SomeStruct становится конкретным (ни от чего не зависящим) типом. Стало быть, Segment<SomeStruct> – это тоже конкретное имя и теперь для обращения Segment<SomeStruct>::Container подсказывать компилятору уже ничего не нужно.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0920 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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