C++ pimpl idiom: Реализация в зависимости от параметра шаблона

В этом вопросе я безуспешно спрашивал, как использовать различную реализацию pimpl в зависимости от аргумент шаблона.

Возможно, этот пример лучше иллюстрирует то, что я пытаюсь сделать:

#include <iostream>

template< int N, typename T >
struct B
{
    B() : c( new C< N > )
    {}

    template< int M >
    struct C;
    C< N > *c;
};

template< int N, typename T >
template< int M >
struct B< N, T >::C
{
    int a[M];
};

// version 1 that doesn't work    
    template< int N, typename T >
    template< >
    struct B< N, T >::C< 0 >
    {
        int a;
    };
// version 2 that doesn't work
    template< typename T >
    template< int M >
    struct B< 0, T >::C
    {
        int a;
    };


int main()
{
    B< 0, float >   b0;
    B< 1, int >     b1;

    std::cout << "b0 = " << sizeof(b0.c->a) << std::endl;
    std::cout << "b1 = " << sizeof(b1.c->a) << std::endl;
}

Это все еще не удается, если я пытаюсь специализировать структуру C (вышеупомянутое не компилируется)

Итак, можно ли сделать?

Я знаю такой обходной путь:

template< int M >
struct D
{
  int a[M];
};
template<  >
struct D<0>
{
  int a;
};

template< int N, typename T >
template< int M >
struct B< N, T >::C
{
    D< M > helper;
};

но если возможно, я хотел бы избежать этого


person BЈовић    schedule 24.03.2011    source источник
comment
Использует ли реальное определение B<N,T>::C<M> N и/или T вообще? Если нет, то почему он должен быть членом шаблона класса B?   -  person aschepler    schedule 24.03.2011
comment
@aschepler Да, использует, но этот пример просто упрощает проблему   -  person BЈовић    schedule 25.03.2011


Ответы (1)


То, что вы пытаетесь сделать, не разрешено языком.

§ 14.7.3.16 (FCD 2010-03-26) гласит:

В явном объявлении специализации для члена шаблона класса или шаблона члена, который появляется в области видимости пространства имен, шаблон члена и некоторые из включающих его шаблонов классов могут оставаться неспециализированными, за исключением того, что объявление не должно явно специализировать шаблон члена класса, если его окружающие шаблоны классов также не являются явно специализированными. В таком явном объявлении специализации шаблон ключевого слова, за которым следует список параметров-шаблона, должен предоставляться вместо шаблона‹>, предшествующего явному объявлению специализации члена. Типы параметров-шаблона в списке-параметров-шаблона должны совпадать с типами, указанными в определении основного шаблона.

[ Example:
template <class T1> class A {
    template<class T2> class B {
        template<class T3> void mf1(T3);
        void mf2();
    };
};
template <> template <class X>

class A<int>::B {
    template <class T> void mf1(T);
};
template <> template <> template<class T>
void A<int>::B<double>::mf1(T t) { }
template <class Y> template <>
void A<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized but
// its enclosing class template A is not
—end example ]
person Nathan Ernst    schedule 24.03.2011
comment
кстати, это § 14.7.3.18 в текущем стандарте С++, и этот абзац отвечает на мой вопрос. Спасибо - person BЈовић; 25.03.2011