Специализация шаблона и наследование

18

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

Как я могу это сделать?

Ниже я хочу достичь, но решение не очень хорошо, потому что это не позволяет мне ссылаться на специализацию для int как Base<int> - мне нужно использовать IntSpec для этого.

#include <iostream>

using namespace std;

template<typename T>
struct Base
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

struct IntSpec : public Base<int>
{
  void print2() {cout << "Base<int>::print2()" << endl;};
};

int main()
{
  Base<double> d;
  // Base<int> i;  <-- I want this kind of instantiation
  IntSpec i;

  d.print1();
  d.print2();
  i.print1();
  i.print2();
}

Вывод:

Base::print1
Base::print2
Base::print1
Base<int>::print2()
    
задан Amadeus 12.06.2013 в 03:59
источник

3 ответа

23

Решение Nicol отлично работает, но это альтернатива:

template<typename T>
struct Base
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

template<>
void Base<int>::print2() {cout << "Base<int>::print2()" << endl;};

Таким образом, вы можете специализировать только определенные функции-члены и по-прежнему использовать те, которые вы не специализировали (в данном случае, print1 ) без каких-либо проблем. Итак, теперь вы будете использовать его так, как хотите:

Base<int> i;
i.print1();
i.print2(); // calls your specialization

Демо здесь .

    
ответ дан mfontanini 12.06.2013 в 05:30
источник
  • Вы уверены, что это стандартный C ++ или расширение компилятора? –  Nicol Bolas 12.06.2013 в 05:43
  • @NicolBolas Я для себя всегда считал, что это совершенно верно (и задавался вопросом, почему это был не самый верный ответ сразу), но это не должно означать ничего (хотя, я думаю, помню, что однажды явным образом искал это в Vandevoorde-Josuttis, и нашел это). –  Christian Rau 12.06.2013 в 09:49
  • @NicolBolas Я считаю, что §14.7.3 / 14 позволяет это делать. Я ошибаюсь? –  mfontanini 12.06.2013 в 14:29
18

Вам просто нужно использовать два класса шаблонов:

template<typename T>
struct CommonBase
{
  void print1() {cout << "Base::print1" << endl;};
  void print2() {cout << "Base::print2" << endl;};
};

template<typename T>
struct Base : public CommonBase<T>
{
};

template<>
struct Base<int> : public CommonBase<int>
{
  void print2() {cout << "Base::print2" << endl;};
};

Вы всегда используете Base , а не CommonBase .

    
ответ дан Nicol Bolas 12.06.2013 в 04:05
источник
4

Другим решением было бы добавить уровень косвенности в функции, которую вы хотите переопределить, т. е.

template<typename T>
struct foo
{
    template<typename T2>
    void bar_impl()
    {
        //generic function
    }

    void bar()
    {
        bar_impl<T>();
    }
};

Затем вы можете специализировать каждую функцию по отдельности для каждого типа или специализировать весь тип по желанию.

    
ответ дан tiridactil 12.06.2013 в 04:09
источник