Подтвердить что ты не робот

Если я хочу специализироваться только на одном методе в шаблоне, как мне это сделать?

Скажем, у меня есть шаблонный класс, например

template <typename T> struct Node
{
    // general method split
    void split()
    {
        // ... actual code here (not empty)
    }
};

Нужно специализироваться на этом случае в случае с треугольным классом.. что-то вроде

template <>
struct Node <Triangle*>
{
    // specialise the split method
    void split() {}
} ;

но я не хочу снова переписывать весь шаблон! Единственное, что нужно изменить, это метод split(), не более того.

4b9b3361

Ответ 1

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

template <typename T> struct Node
{
    // general method split
    void split()
    {
        // implementation here or somewhere else in header
    }
};

//прототип функции, объявленной в cpp   void splitIntNode (Node и Node);

template <>
void Node<int>::split()
{
     splitIntNode( this ); // which can be implemented
}

int main(int argc, char* argv[])
{
   Node <char> x;
   x.split(); //will call original method
   Node <int> k;
   k.split(); //will call the method for the int version
}

Если splitIntNode нужен доступ к закрытым членам, вы можете просто передать эти члены в функцию, а не весь Node.

Ответ 2

Просто определите некоторые

template<>
void Node<Triangle*>::split()
{
}

после основного шаблона, но до того, как вы впервые его создадите.

Ответ 3

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

Например, это работает:

template<typename T, typename U>
struct Node
{
    void function() { cout << "Non-specialized version" << endl; }
};

template<>
void Node<int, char>::function() { cout << "Specialized version" << endl; }

Частично специализированная версия, однако, не будет работать:

template<typename T, typename U>
struct Node
{
    void function() { cout << "Non-specialized version" << endl; }
};

template<typename U>
void Node<int, U>::function() { cout << "Specialized version" << endl; }

Что вы можете делать, если вы обнаружите себя во втором сценарии, чтобы избежать ненужного дублирования кода, он объединяет все общие элементы в общий базовый класс, а затем помещает все элементы, которые будут варьироваться с частичной специализацией в производном классе. Таким образом, вам не нужно повторно дублировать весь общий код в базовом классе, вам нужно будет только переписать определения для специализированного производного класса.

Ответ 4

Неловкий метод, который я обычно использую: Объявите "базовую" реализацию шаблона. Затем объявите свою реализацию шаблона, реализация по умолчанию просто наследует "базовую". Настройка будет наследовать "основные", плюс переопределить конкретные методы. Вот так:

template <typename T> struct NodeBase
{
    // methods
};

template <typename T> struct Node
    :public NodeBase<T>
{
    // nothing is changed
};

template <> struct Node<SpecificType>
    :public NodeBase<SpecificType>
{
    // re-define methods you want
};

Обратите внимание, что "переопределение метода" не имеет ничего общего с виртуальными функциями или т.д. Это просто объявление функции с тем же именем и параметрами, что и в базе, - компилятор автоматически ее использует.