Может ли внутренний класс класса шаблона быть классом, не являющимся шаблоном?

Я создаю класс шаблона с внутренним служебным классом. Все специализации шаблона требуют одного и того же внутреннего класса:

template<...> class Outer {
    class Inner { };
};

Это дает мне Outer<...>::Inner, но я хочу, чтобы все Inner были одного типа, как если бы я только что написал:

class Inner { };
template <...> class Outer { };

или если бы Outer просто не был классом-шаблоном:

class Outer {
    class Inner { };
};

давая мне Outer::Inner. Я бы хотел, чтобы Outer::Inner работало для всех Outer<>, если это возможно (просто из соображений пространства имен/ясности). В противном случае, конечно, я могу просто убрать Inner.


person Ben Jackson    schedule 19.07.2011    source источник
comment
Я совершенно уверен, что ответ отрицательный, но я надеюсь, что кто-то докажет, что я ошибаюсь, потому что я оказался в похожей ситуации :)   -  person Dennis Zickefoose    schedule 20.07.2011
comment
Я только достаточно уверен, что ответ отрицательный, но я также надеюсь на умные обходные пути...   -  person Ben Jackson    schedule 20.07.2011


Ответы (3)


Вложенный класс может быть нешаблонным, но каждый экземпляр шаблона будет иметь свой собственный вложенный класс, потому что они (иначе) не связанные типы. Ты можешь сделать

namespace detail {

class Inner {};

} // detail

template<...>
class Outer {
    typedef detail::Inner Inner;
};
person Luc Danton    schedule 19.07.2011
comment
Я забыл детали своего пространства имен - можно ли теперь class Inner скрыть, как в настоящем внутреннем классе? Или любой в том числе код сможет иметь на это? - person Nate; 20.07.2011
comment
@Nate Вышеприведенное ведет себя как с любым typedef. Inner можно оставить неполным только с объявлением, которое не является также определением (т. е. class Inner;), со всеми вытекающими из него оговорками. Но оно должно быть объявлено (имя detail::Inner должно на что-то ссылаться), иначе оно не может быть typedef создано. - person Luc Danton; 20.07.2011

То, как я делал это в прошлом, использует наследование:

class DummyBase{
protected:
    class Inner{
        //etc...
    };
};

template<...> class Outer : public DummyBase{
    //etc...
};
person Nate    schedule 19.07.2011
comment
+1, потому что это делает Outer<>::Inner настоящим именем класса. Таким образом, class Outer<>::Inner x; или friend class Outer<>::Inner; по-прежнему будут работать, тогда как решение typedef здесь не сработает. - person Johannes Schaub - litb; 20.07.2011

Он будет уникальным для каждого экземпляра Outer. то есть,

Outer<int>::Inner will be a different type from Outer<double>::Inner
person John    schedule 19.07.2011
comment
Этот факт хорошо известен ОП, поскольку он ясно указал на это в своей проблеме. - person Armen Tsirunyan; 20.07.2011