C ++ - Специализация шаблонов и частичная специализация

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

У меня есть шаблонный класс:

template <class T, int x, int y>
class Z {
    T **array[x][y];
    public:
         Z();
         void print();
         //and other methods
};

Мне необходимо:

1) Только Z, где x = 2 и y = 2, должны иметь общедоступный метод void J ()

2) Для char Z x = 2 и y = 2 J что-то сделает; для всего остального он делает что-то еще

3) Только для Z, где T - char, массив будет инициализирован некоторым значением. Для всего остального это 0

Естественно, это работает:

template<class T, int x, int y>
Z<T,x,y>::Z<T,x,y>() { //initialize to 0 } 

Но это не так:

template<int x, int y>
Z<char,x,y>::Z<char,x,y>() { //initialize to something}

И аналогично (предположим, что J существует) это не работает:

template <class T>
void Z<T,2,2>::J() { //something }

У меня вопрос:

Есть ли простой способ реализовать вышеперечисленные пункты? Мне нужно сохранить все остальные методы в Z. Подсказка или указание в правильном направлении (возможно, я пропустил вопрос, так как их много) было бы полезно.

Спасибо.


person aoi    schedule 18.11.2012    source источник
comment
Какие у вас ошибки? Что такое J? Непонятно, чем вы хотите заниматься.   -  person Synxis    schedule 19.11.2012
comment
J - некоторая функция. То, что мне нужно сделать, перечислено 1,2,3. Мои ошибки (следующие комментарии):   -  person aoi    schedule 19.11.2012
comment
Для Z ‹char, x, y› :: Z ‹char, x, y› () {// stuff}: ожидаемый конструктор, деструктор или преобразование типа перед токеном '‹' и ожидаемым ';' перед токеном '‹'   -  person aoi    schedule 19.11.2012
comment
И если предположить, что J существует: void Z ‹char, x, y› :: J () {// stuff} дает ошибки: недопустимое использование неопределенного типа class Z<char, x, y>'" and "template definition of non-template void Z ‹char, x, y› :: J () '   -  person aoi    schedule 19.11.2012


Ответы (2)


Похоже, вы хотите определить только некоторые функции некоторых специализаций: если print() не меняется между специализацией char и общим случаем, похоже, вы не хотите его переопределять.

// What you want to do (illegal in C++)
template<int,typename T>
struct Z
{
    T myValue;
    Z();
    void print() { /* ... */ }
};

template<int i, typename T>
Z<i,T>::Z() { /* ... */ }

template<int i>
Z<i,char>::Z() { /* ... */ }

Однако это не работает. Частичная или полная специализация класса почти не имеют ничего общего, кроме "прототипа" параметров шаблона:

// The two following types have only two things related: the template parameter is an int,
// and the second type is a full specialization of the first. There are no relations between
// the content of these 2 types.
template<int> struct A {};
template<> struct A<42> { void work(); };

Вы должны объявить и определить каждую (частичную) специализацию:

// Fixed example
template<int,typename T>
struct Z
{
    T myValue;
    Z();
    void print() { /* ... */ }
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }

// Specialization for <all-ints,char>
template<int i>
struct Z<i,char>
{
    char myValue;
    char othervalue;
    Z();
    void print() { /* Same code than for the general case */ }
};

template<int i>
Z<i,char>::Z() { /* ... */ }

Единственный способ избежать дублирования кода - использовать наследование признаков:

// Example with the print function
template<typename T>
struct print_helper
{
    void print() { /* ... */ }
};

// Fixed example
template<int,typename T>
struct Z : public print_helper<T>
{
    T myValue;
    Z();
};
template<int i, typename T>
Z<i,T>::Z() { /* ... */ }

// Specialization for <all-ints,char>
template<int i>
struct Z<i,char> : public print_helper<char>
{
    char myValue;
    char othervalue;
    Z();
};

template<int i>
Z<i,char>::Z() { /* ... */ }

На данный момент вы не можете делать то, что хотите, без дублирования (функция удаления дублирования кода - static if и была предложена для следующего стандарта C ++, см. n3322 и n3329).

person Synxis    schedule 18.11.2012
comment
Да, я в курсе. Но я хотел знать, есть ли более простой способ сделать это, не дублируя код повсюду. (Потому что, очевидно, это очень плохо) - person aoi; 19.11.2012
comment
Это не наследование, поскольку вам все равно придется дублировать код повсюду в вашем решении (как и раньше). В любом случае постараюсь заставить работать какое-нибудь наследование. - person aoi; 19.11.2012

Вы можете ознакомиться с этим курсом http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-5-из-n

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

template<typename T> struct helper {
    static void doThingy(){}
};

template<typename X> struct helper<X*> {
    static void doThingy(){}
};

Helper(double*)::doThingy();

В этом примере вы хотите специализировать поведение в doThingy () только тогда, когда тип в шаблоне является типом указателя. В этом случае нельзя использовать перегрузку метода doThingy (). Это потому, что вы не можете перегрузить функцию без аргументов. Но вы можете иметь частичную специализацию помощника структуры. В специализированном шаблоне вы реализовали желаемое поведение для doThingy ().

person kiriloff    schedule 12.05.2014