специализировать шаблон члена без специализации его родителя - PullRequest
10 голосов
/ 06 января 2010

У меня есть шаблон класса, вложенный в другой шаблон. Частично специализировать это легко: я просто объявляю еще один блок template< … > внутри его родителя.

Однако мне нужна еще одна частичная специализация, которая указывает все аргументы локального шаблона. Это превращает это в явную специализацию. Явные специализации по какой-либо причине должны находиться в области имен. Чтобы объявить его вне родительского класса, родительский объект должен быть назначен, что требует непустого списка аргументов шаблона. Это подразумевает частичную специализацию. Частичная специализация - это , что я делаю, и она должна работать в произвольной внешней области. Но и GCC, и Comeau не смогли определить параметр шаблона в номинации родителей с формальными аргументами частичной специализации.

template< class X > struct A {
    template< class Y > struct B; // initial declaration OK

    template< class Z >
    struct B< A< Z > > {}; // partial OK as long as there's a local arg

    template<> // ERROR: this syntax triggers explicit specialization
    struct B< int > {};
};

template<> // ERROR: can't nest template<>s here (why?)
template< class X > // ERROR: can't deduce X from type of A<X>::B<int> (why?)
struct A< X >::B< int > {};

(Я оставил весь свой нерабочий код; закомментируйте его соответствующим образом, чтобы попытаться разобраться.)

Ответы [ 4 ]

9 голосов
/ 06 января 2010

Это незаконно по стандарту C ++ 14.7.3 / 18:

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

4 голосов
/ 06 января 2010

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

Поэтому я бы предложил другой обходной путь:

namespace detail
{
  template <class X, class Z> class BImpl;
  template <class X, class Z> class BImpl<X, A<Z> > {};
  template <class X> class BImpl<X,int> {};
}

template <class X>
class A
{
  template <class Z> struct B: BImpl<X,Z> {};
};

Просто отметьте, что требуется передать X в качестве аргумента BImpl, если вы когда-нибудь захотите также специализировать A. Самое смешное, что в этом случае я получаю только частичную специализацию!

0 голосов
/ 06 января 2010

По крайней мере, это работает в VC 2010. Но я не могу написать определение. из fun () для "int" вне объявления класса. РЕДАКТИРОВАТЬ: К сожалению, g ++ также имеет проблемы с компиляцией. РЕДАКТИРОВАТЬ: приведенный ниже код работал на VC 2010.

template<typename X>
class A
{
public:
    A()
    {

    }

    template<typename Y>
    struct B
    {
        void fun();
    };

    template<>
    struct B<int>
    {
        void fun()
        {
            cout << "Specialized version called\n";
        }
        //void fun();
    };



public:

    B<X> b;
};



template<typename X>
template<typename Y>
void A<X>::B<Y>::fun()
{
    cout << "templated version called\n";
}

int main()
{
   A<int> a;
    a.b.fun();
    A<float> a1;
    a1.b.fun();
}
0 голосов
/ 06 января 2010

Сложные вещи. Ваш начальный код ICE VC10 Beta2, хорошо.

Прежде всего, я думаю, что у вас есть это задом наперед:

template<> 
template< class X > 
struct A< X >::B< int > {};

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

template< class X > 
template<> 
struct A< X >::B< int > {};

Но даже это не компилируется. Текст ошибки действительно полезен, хотя:

a.cpp a.cpp (11): ошибка C3212: «A :: B»: явный специализация члена шаблона должен быть членом явного специализация a.cpp (8): см. объявление 'A :: B'

Похоже, что вполне законно полностью специализировать B, если вы также полностью специализируете A.

Редактировать : Хорошо, я слышал от кого-то, кто может авторитетно говорить об этом - перефразируя, это очень мутная область в стандарте, и это открытая проблема с Комитетом C ++, чтобы очистить его up («это» - явная специализация членов шаблонов классов). В ближайшей перспективе совет: «Не делай этого».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...