2008-10-02 5 views
26

Следующий код:«недопустимое использование неполного типа» ошибка с частичной специализации шаблона

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() { 
} 

тогда он скомпилируется правильно.

ответ

32

Вы не можете частично специализировать функцию. Если вы хотите сделать это в функции-члене, вы должны частично специализировать весь шаблон (да, это раздражает). На большом шаблоном классе, чтобы частично специализировать функцию, вам понадобится обходной путь. Возможно, будет работать шаблонная структура элемента (например, template <typename U = T> struct Nested). Или вы можете попробовать получить другой шаблон, который частично специализируется (работает, если вы используете нотацию this->member, иначе вы столкнетесь с ошибками компилятора).

3

Если вам нужно частично специализировать конструктора, вы можете попробовать что-то вроде:

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. 
    } 
}; 

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

5

Хотя 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) ... 
}; 
Смежные вопросы