template <typename X> //Допустим мы обещаем, что в Х будет определён тип Typeclass A
{
private:
typedef X::Type myType;
/*
..........................
*/
}
template <typename X>
class B : public A<X>
{
myType myMember;//Будет ли здесь определён тип myType по стандарту
}
Более общий случай:
class A
{
private:
typedef unsigned int uint;
}
class B: public A
{
uint bbb;//?????????????????
}
Здравствуйте, Слава, Вы писали:
С>Добрый день.
С>Хочется написать что-то такое:
С>
С>template <typename X> //Допустим мы обещаем, что в Х будет определён тип Type
С>class A
С>{
С>private:
С> typedef X::Type myType; // перед X::Type нужен typename
С>/*
С>..........................
С>*/
С>}
С>
A::myType закрытый тип класса A, он может использоваться только членами класса A или его друзьями.
С>Более общий случай:
С>
С>class A
С>{
С>private:
С> typedef unsigned int uint;
С>}
С>class B: public A
С>{
С> uint bbb;//?????????????????
С>}
С>
С>Этот код компилируется в MSVS2008, но не в GCC
Не надо нас обманывать, этот код не компилируется ни одной из версий MSVC или GCC, хотя бы из-за отсутсвия ; после определения класса. В то, что MSVC2008 позволяет обращаться к закрытым членам класса, тоже не верится, или ты имел в виду, что компилируется шаблонный вариант? Тогда это известная бага MSVC (разных версий): он позволяет писатьв шаблонах практически, что угодно, и будет пытаться копмпилировать это только при инстанцировании этого шаблона.
template <class T>
class Foo
{
public:
Foo()
{
typedef ~~~ +++;
+++ *x = new ~~~();
}
};
Впрочем, из-за отсутсвия typename и ; первый вариант тоже не компилируется, даже MSVC2008.
The last good thing written in C was Franz Schubert's Symphony No. 9.
Здравствуйте, crable, Вы писали:
C>Здравствуйте, Слава, Вы писали:
С>>Добрый день.
С>>Хочется написать что-то такое:
С>>
С>>template <typename X> //Допустим мы обещаем, что в Х будет определён тип Type
С>>class A
С>>{
С>>private:
С>> typedef X::Type myType; // перед X::Type нужен typename
Хорошо, typename.
С>>Этот код компилируется в MSVS2008, но не в GCC
C>Не надо нас обманывать, этот код не компилируется ни одной из версий MSVC или GCC, хотя бы из-за отсутсвия ; после определения класса.
Вопрос теоритический, поэтому код набивался прямо в фаерфоксе.
C>A::myType закрытый тип класса A, он может использоваться только членами класса A или его друзьями.
Хорошо, допустим, что typename/ typedef определены в секции protected.
class A
{
protected:
typedef unsigned int uint;
};
class B: public A
{
uint bbb;//?????????????????
};
Можно ли в наследуюшем классе обращаться к типу, определённому в наследуемом без указания имени неследуемого класса:
Так как здесь написано, компилируется в MSVS2008, GCC требует писать A::uint;
Кто-нибудь знает, что говорит стандарт, я не нашёл, но надеюсь найти здесь тех, кто знает где искать (т.е. работает более плотно со стандартом)
Здравствуйте, Слава, Вы писали:
С>Здравствуйте, crable, Вы писали:
C>>Здравствуйте, Слава, Вы писали:
С>>>Добрый день.
[snip]
C>>Не надо нас обманывать, этот код не компилируется ни одной из версий MSVC или GCC, хотя бы из-за отсутсвия ; после определения класса. С>Вопрос теоритический, поэтому код набивался прямо в фаерфоксе.
Это, понятно, просто, я, например, предпочёл бы увидеть минимальный компилируемый/некомпилирыемый пример, чтобы не надо было гадать в чём вопрос (не у все же тут телепаты
).
C>>A::myType закрытый тип класса A, он может использоваться только членами класса A или его друзьями. С>Хорошо, допустим, что typename/ typedef определены в секции protected.
С>
С>class A
С>{
С>protected:
С> typedef unsigned int uint;
С>};
С>class B: public A
С>{
С> uint bbb;//?????????????????
С>};
С>
С>Можно ли в наследуюшем классе обращаться к типу, определённому в наследуемом без указания имени неследуемого класса: С>Так как здесь написано, компилируется в MSVS2008, GCC требует писать A::uint;
Для этого примера, GCC ничего подобного не требует. Это необходимо только для шаблонных классов.
templace <class T>
struct A
{
typedef int MyInt;
};
template <class T>
struct B : public A<T> // Тип базового класса зависит от типа T, пока ещё не известного, т.е. мы не знаем что содержит A<T>
{
MyInt y; // как, по-твоему, компилятор догадается, что MyInt это тип, определённый в A?
};
struct C : public A<void> // Тип базового класса полностью известен и мы уже знаем, есть там MyInt или нет.
{
MyInt y;
};
С>Кто-нибудь знает, что говорит стандарт, я не нашёл, но надеюсь найти здесь тех, кто знает где искать (т.е. работает более плотно со стандартом)
Более формально смотри 14.6.2 пункт 3 (как раз твой пример) да и вообще весь 14.6 можно почитать.
The last good thing written in C was Franz Schubert's Symphony No. 9.
Здравствуйте, crable, Вы писали:
C>Здравствуйте, Слава, Вы писали:
С>>Здравствуйте, crable, Вы писали:
C>>>Здравствуйте, Слава, Вы писали:
С>>>>Добрый день.
[snip]
С>>Кто-нибудь знает, что говорит стандарт, я не нашёл, но надеюсь найти здесь тех, кто знает где искать (т.е. работает более плотно со стандартом)
C>Более формально смотри 14.6.2 пункт 3 (как раз твой пример) да и вообще весь 14.6 можно почитать.
Да, ещё нужно добавить, что префикс A:: делает тип зависимым от параметра шаблона и откладывает поиск имени на время инстанцирования (2-х фазный поиск имён). Что такое зависимые типы описано в 14.6.2.1.
The last good thing written in C was Franz Schubert's Symphony No. 9.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Слава, Вы писали:
С>... С>Хорошо, typename. С>... С>Хорошо, допустим, что typename/ typedef определены в секции protected. С>... С>Можно ли в наследуюшем классе обращаться к типу, определённому в наследуемом без указания имени неследуемого класса?...
Начнем с нешаблонного варианта. Кстати, то что нешаблонный вариант является более общим, чем шаблонный, вопрос весьма спорный. Из сказанного ниже должно быть понятно почему. Итак, использование в наследнике открытого или защищенного типа, объявленного в базовом классе, разрешено автоматом и не требует каких-либо дополнительных объявлений:
class A
{
protected:
typedef unsigned int uint;
};
class B : public A
{
uint bbb;
};
Иная ситуация с шаблонными классами. Особенность заключается в том, что от места определения шаблонного класса-наследника до места его использования(инстанцирования) шаблонный *базовый* класс может быть сто раз специализирован. И будет ли присутствовать в этих специализациях упомянутый тип — это большой вопрос. Поэтому компилятор, встретив в производном классе использование незнакомого типа, даже не обязан искать его объявление в базовом классе, он имеет право просто сообщить об ошибке. А исправить эту ошибку можно, использовав using-объявление, которым мы сообщим компилятору, что данный идентификатор *должен* быть определен в базовом классе. Кроме того, нужно не забыть о ключевом слове typename, чтобы компилятор знал также, что этот идентификатор обозначает имя типа:
template <typename X>
class A
{
protected:
typedef typename X::Type myType;
};
template <typename X>
class B : public A<X>
{
using typename A<X>::myType;
myType myMember;
};
С>Кто-нибудь знает, что говорит стандарт, я не нашёл, но надеюсь найти здесь тех, кто знает где искать (т.е. работает более плотно со стандартом)
Стандарт говорит примерно то же. Вот только номера пунктов искать сейчас некогда.
--
Не можешь достичь желаемого — пожелай достигнутого.