Специализированная шаблонная функция для шаблонного класса - PullRequest
2 голосов
/ 17 февраля 2012

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

Вот основной пример: test.h:

template <class T>
class myC {
    T x;
};

template <class U>
void f(U y) {
}

template <>
template <class T>
void f<myC<T> >(myC<T> y) {
}

test.cpp

#include "test.h"
int main() {
    myC<double> m;
    f(m);
}

GCC 4.6.1 выдает мне следующее сообщение об ошибке:

In file included from test.cpp:1:0:
test.h:13:25: error: too many template parameter lists in declaration of ‘void f(myC<T>)’
test.h:13:6: error: template-id ‘f<myC<T> >’ for ‘void f(myC<T>)’ does not match any template declaration
test.h:13:25: note: saw 2 ‘template<>’, need 1 for specializing a member function template

Возможно ли это вообще?Или есть другой способ достижения той же цели?

Ответы [ 3 ]

4 голосов
/ 17 февраля 2012
template <>
template <class T>
void f<myC<T> >(myC<T> y) {
}

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

Шаблон функции либо полностью специализированный или не специализированный вообще.Спецификация языка не допускает частичной специализации шаблона функции.

Таким образом, вы можете перегрузить шаблон функции следующим образом:

template <class T>
void f(myC<T> y)  //note that it is overload, not specialization
{ 
}

, что разрешено и предпочтительнее, чемдаже полная специализация шаблона.

Прочитайте эти статьи Херба Саттера:

2 голосов
/ 17 февраля 2012

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

template <class U> void f(U y) {}
template<> void f<double>(double y) {} // specialization for double

Обратите внимание, что аргумент шаблона не нужно явно указывать, если его можно вывести из контекста:

template<> void f<>(int y) {} // specialization for int

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

template <class T>
class myC {
    T x;
};

template <class U>
void f(U y) {
}

template <class T>
void f(myC<T> y) {
}

int main() {
    myC<double> m;
    f(m);
    return 0;
}
0 голосов
/ 17 февраля 2012

Насколько я могу сказать, вы не можете специализировать шаблонные функции, только шаблонные классы (или структуры).

Но это вряд ли ограничение: просто объявите структуру со статическими открытыми функциями-членами и создайте шаблонпараметры для структуры:

template <class T>
class myC {
    T x;
};

template <class U>
struct Foo
{
    static void f(U y) {
    }
};

template <>
template <class T>
struct Foo<myC<T> >
{
    static void f(myC<T> y) {
    }
};

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

template <class U>
void f(U y) {
    return Foo<U>::f(y);
}
...