Специализация метода шаблона класса С++

214
16 июня 2017, 10:13

У меня есть шаблон класса. Я захотел добавить метод, но только для одного конкретного типа. При использовании частичной специализации, по сути, нужно переписывать все поля и методы, даже если я их не изменяю. В итоге, при изменении чего-то общего, приходиться менять код в 2 местах. Подскажите, есть ли какой-то другой способ реализации такого специального метода или как избежать такого неудобства?

UPD: С методом разобрался, спасибо. Но возникает вопрос, как тогда действовать, если нужно добавить атрибут?

Answer 1

Если у вас есть шаблон класса, то его методы являются независимыми шаблонами и специализировать их можно независимо. Т.е. для этого не надо специализировать весь класс заново

template <typename T> struct Class
{
   int i;
   void foo()
   {
      i = 5;
      std::cout << "Generic implementation" << std::endl;
   }
};
template <> void Class<int>::foo()
{
  i = 42;
  std::cout << "Specialized implementation" << std::endl;
}
int main()
{
  Class<double> d;
  d.foo();
  std::cout << d.i << std::endl;
  Class<int> i;
  i.foo();
  std::cout << i.i << std::endl;
}

Однако добавить метод, которого изначального нет в основном шаблоне таким способом не получится. Если вам нужно именно добавить метод, то возможно имеет смысл объявить этот метод в главном шаблоне (не определяя его, или определив его как deleted), а потом уже предоставлять специализации вышеописанным способом.

Answer 2

GCC компилирует следующий код:

#include <iostream>
#include <string>
using namespace std;
template <class T>
struct A
{
    A(T x) : x(x) {}
    void foo() = delete; // { cout << "default: " << x << endl; }
    void bar() { cout << "bar: " << x << endl; }
    T x;
};
template<>
void A<int>::foo()
{
    cout << "int: " << x << endl;
}

int main()
{
    A<int> a(0);
    a.foo();
    a.bar();
    A<double> b(0);
    // b.foo(); // - не компилируется
    b.bar();
    A<string> c("hello");
    // c.foo(); // - не компилируется
    c.bar();
    return 0;
}

Собственно, если заменить = delete, на закомментированный код, все будет работать, как в ответе AnT.

READ ALSO
Segmentation fault на QSqlQuery::exec

Segmentation fault на QSqlQuery::exec

Есть такой код

240
отличия operator new и expression new

отличия operator new и expression new

В чем разница между operator new и expression new?

267
Односвязный линейный список [требует правки]

Односвязный линейный список [требует правки]

Помогите выполнить задачу:

245
Работа с Unicode в Cython

Работа с Unicode в Cython

Имеется скрипт, написанный на Cython, который принимает на вход массив C++ строк, анализирует их с помощью pymorphy2 и обрабатывает результаты анализаВ...

382