2010-02-18 5 views
7

Рассмотрим следующий пример:Как мы typedef или переопределим шаблонный вложенный класс в подклассе?

template <typename T> 
class Base { 
    public: 
    template <typename U> 
    class Nested { }; 
}; 

template <typename T> 
class Derived : public Base<T> { 
    public: 
    //How do we typedef of redefine Base<T>::Nested? 
    using Base<T>::Nested; //This does not work 
    using Base<T>::template<typename U> Nested; //Cannot do this either 
    typedef typename Base<T>::template<typename U> Nested Nested; //Nope.. 

    //now we want to use the Nested class here 
    template <typename U> 
    Class NestedDerived : public Nested { }; 

    //or like this: 
    Nested<int> nestedVar; // obviously does not work 
}; 

Как использовать шаблонный класс вложенной в производном классе? Можно ли это сделать в текущей версии стандарта C++?

+0

Я не понимаю, почему вы делаете Вложенный «производный» класс, потому что класс Derived наследует класс Nested. – Craig

+0

Я хочу, чтобы «вложенный» класс был инкапсулирован в «Base», а класс «Derived» может расширять или использовать класс «Base :: Nested». – leiiv

+0

В каком случае используется 'using Base :: Nested;' не работает? –

ответ

10

Собственно using работает как рекламируется, он просто не избавиться от вопроса имен зависит в шаблоне, и это может в настоящее время не псевдоним шаблонов непосредственно (будет fixed in C++0x):

template <class T> 
struct Base { 
    template <class U> struct Nested {}; 
}; 

template <class T> 
struct Derived : Base<T> { 
    using Base<T>::Nested; 

    // need to prefix Nested with template because 
    // it is a dependent template: 
    struct X : Base<T>::template Nested<int> {}; 

    // same here: 
    template<class U> 
    struct Y : Base<T>::template Nested<U> {}; 

    // data member, typename is needed here: 
    typename Base<T>::template Nested<int> data; 
}; 

void f() { 
    Derived<int>::Nested<int> n; // works fine outside 
} 

Существует еще один возможный Гоча при использовании Derived<T>::Nested в шаблонах, но опять-таки, что это вопрос имя-зависимый, не наследование, связанные с:

template<class T> 
void g() { 
    // Nested is a dependent type and a dependent template, thus 
    // we need 'typename' and 'template': 
    typedef typename Derived<T>::template Nested<int> NestedInt; 
} 

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

  • с префиксом typename, если его зависимый тип: typename A<T>::B
  • непосредственно с префиксом template, если его зависимый шаблон: A<T>::template f<int>()
  • как если оба: typename A<T>::template B<int>
  • typename является незаконным в базовом классе списках: template<class T> struct A : B<T>, C<T>::template D<int> {};
+0

Можете ли вы привести пример использования типа Nested для члена данных класса Derived? Если нам еще нужно использовать 'Base ::', то будет ли использоваться 'using Base :: Nested'? – leiiv

+1

сделаю. 'using Base :: Nested' не бесполезен, хотя он используется в' f() 'и' g() '- без объявления' using', вам нужно будет получить доступ к 'Nested' через' Base' в ' F() '. –

+0

Спасибо, gf, это очень полезно. – leiiv

0

Попробуйте это:

template <typename T> 
class Base { 
    public: 
    template <typename U> 
    class Nested { }; 
}; 

template <typename T> 
class Derived : public Base<T> { 
    public: 
    //How do we typedef of redefine Base<T>::Nested? 
    //using Base<T>::Nested; //This does not work 
    //using Base<T>::template<typename U> Nested; //Cannot do this either 
    //typedef typename Base<T>::template<typename U> Nested Nested; //Nope.. 

    //now we want to use the Nested class here 
    template <typename U> 
    class NestedDerived : public Base<T>::template Nested<U> { }; 
}; 

int main() 
{ 
    Base<int>::Nested<double> nested; 

    Derived<int>::NestedDerived<double> nested_derived; 

    return 0; 
} 

Составитель штраф с помощью GCC 4.3.3 на Slackware 13

+0

Прошу прощения, но это не то, что я прошу. Я хочу знать, можно ли ввести typedef или использовать 'public Base :: template Nested ' внутри класса 'Derived', потому что этот тип будет использоваться во многих местах. – leiiv

+0

Хорошо, я попробую найти подходящий ответ – coelhudo

0

Я все еще не 100% уверен, что вы хотите, но вы можете попробовать.
Это составленное на Visual Studio

template <typename T> 
class Base { 
    public: 
    template <typename U> 
    class Nested { }; 
}; 

template <typename T> 
class Derived : public Base<T> { 
    public: 
    //now we want to use the Nested class here 
    template <typename U> 
    class NestedDerived : public Nested<U> { }; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
Base<int>::Nested<double> blah2; 
Derived<int>::NestedDerived<int> blah; 

return 0; 
} 
+0

это также можно использовать \t Производные :: Вложенные blah3; – Craig

+0

ah good ol 'VS .. g ++ 4.4.1 не позволяет мне это делать .. – leiiv

+0

В чем разница между тем, что я сделал и что сделал Крейг? Я действительно не заметил:/ – coelhudo

2

Это похоже на работу:
(EDIT:.! добавил еще несколько строк, чтобы показать первое утверждение шаблона И благодаря Самиру Talwar для коррекции моего форматирования)

template <typename T, typename U> 
class Derived : public Base<T> { 
    public: 
    typedef typename Base<T>::template Nested<U> Nested; 

    class NestedDerived : public Nested { }; 

    Nested nestedVar; 
}; 
+0

Но теперь пользователям всегда нужно указать второй аргумент шаблона для 'Derived'. –

+0

Да, и один Derived не может иметь более одного типа NestedDerived. Это серьезное ограничение, но в противном случае я не вижу никакого способа, чтобы NestedDerived использовал Base :: Nested. – Beta

Смежные вопросы