2008-10-02 22 views
26

El siguiente código:"uso inválido de tipo incompleto" error con especialización de plantilla parcial

template <typename S, typename T> 
struct foo { 
    void bar(); 
}; 

template <typename T> 
void foo <int, T>::bar() { 
} 

me da el error

invalid use of incomplete type 'struct foo<int, T>' 
declaration of 'struct foo<int, T>' 

(. Estoy usando gcc) es mi sintaxis de parcial especialización mal? Tenga en cuenta que si elimino el segundo argumento:

template <typename S> 
struct foo { 
    void bar(); 
}; 

template <> 
void foo <int>::bar() { 
} 

y luego se compila correctamente.

Respuesta

32

No se puede especializar parcialmente una función. Si desea hacerlo en una función miembro, debe especializar parcialmente toda la plantilla (sí, es irritante). En una clase de plantilla grande, para especializar parcialmente una función, necesitaría una solución alternativa. Tal vez una estructura de miembro con plantilla (por ejemplo, template <typename U = T> struct Nested) funcionaría. O bien, puede intentar derivar de otra plantilla que se especialice parcialmente (funciona si usa la notación this->member, de lo contrario, encontrará errores de compilación).

3

Si necesita especializarse parcialmente un constructor, puede intentar algo como:

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

Nota: esto se anonimizada de algo que estoy trabajando. También puede usar esto cuando tenga una clase de plantilla con muchos y muchos miembros y solo quiera agregar una función.

5

Aunque coppro ya mencionó dos soluciones y Anonymous explicó la segunda, me tomó bastante tiempo entender la primera. Tal vez el siguiente código sea útil para alguien que tropiece con este sitio, que aún ocupa un lugar destacado en Google, como yo. El ejemplo (pasar un vector/matriz/elemento individual de numericalT como dataT y luego acceder a él vía [] o directamente) es, por supuesto, un tanto artificial, pero debe ilustrar cómo realmente puede acercarse a la especialización parcial de una función miembro envolviéndola en una clase parcialmente especializada.

/* 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) ... 
}; 
Cuestiones relacionadas