Ошибка недопустимого использования неполного типа с частичной специализацией шаблона
Следующий код:
template <typename S, typename T>
struct foo {
void bar();
};
template <typename T>
void foo <int, T>::bar() {
}
дает ошибку
invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'
(Я использую gcc.) Является ли мой синтаксис для частичной специализации неправильным? Обратите внимание, что если я удалю второй аргумент:
template <typename S>
struct foo {
void bar();
};
template <>
void foo <int>::bar() {
}
то он правильно компилируется.
Ответы
Ответ 1
Вы не можете частично специализировать функцию. Если вы хотите сделать это в функции-члене, вы должны частично специализировать весь шаблон (да, это раздражает). На большом шаблоном классе, чтобы частично специализировать функцию, вам понадобится обходной путь. Возможно, будет работать шаблонная структура элемента (например, template <typename U = T> struct Nested
). Или вы можете попробовать получить другой шаблон, который частично специализируется (работает, если вы используете нотацию this->member
, иначе вы столкнетесь с ошибками компилятора).
Ответ 2
Если вам нужно частично специализировать конструктор, вы можете попробовать что-то вроде:
template <class T, int N>
struct thingBase
{
//Data members and other stuff.
};
template <class T, int N> struct thing : thingBase<T, N> {};
template <class T> struct thing<T, 42> : thingBase<T, 42>
{
thing(T * param1, wchar_t * param2)
{
//Special construction if N equals 42.
}
};
Примечание: это было анонимное из того, над чем я работаю. Вы также можете использовать это, когда у вас есть класс шаблонов с множеством и количеством членов, и вы просто хотите добавить функцию.
Ответ 3
Хотя coppro упомянул два решения уже, и Аноним объяснил второй, мне потребовалось некоторое время, чтобы понять первый. Возможно, следующий код поможет кому-то споткнуться по этому сайту, который по-прежнему занимает высокое место в google, как и я. Пример (передача вектора/массива/одиночного элемента числовой Т как dataT, а затем доступа к нему через [] или непосредственно), конечно, несколько придумана, но должна проиллюстрировать, как вы действительно можете приблизиться к частичному специализации функции-члена, обернув ее в частично специализированном классе.
/* The following circumvents the impossible partial specialization of
a member function
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */
//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
numericalT& access(dataT& x, const unsigned int index){return x[index];}
};
//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
numericalT& access(dataT& x, const unsigned int index){return x;}
};
//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
dataT x;
specialised<dataT,numericalT,dataDim> accessor;
public:
//... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};