error "uso no válido de tipo incompleto" con especialización de plantilla parcial


El siguiente código:

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 incorrecta mi sintaxis para especialización parcial? Tenga en cuenta que si elimino el segundo argumento:

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

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

Entonces se compila correctamente.

Author: Jesse Beder, 2008-10-03

3 answers

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 con plantilla grande, para especializar parcialmente una función, necesitaría una solución alternativa. Tal vez una estructura miembro templada (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 compilador).

 34
Author: coppro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-03 00:05:53

Aunque coppro ya mencionó dos soluciones y Anonymous explicó la segunda, me tomó bastante tiempo entender la primera. Tal vez el siguiente código es útil para alguien que tropieza con este sitio, que todavía ocupa un lugar alto en Google, como yo. El ejemplo (pasar un vector/array / single element de numericalT como dataT y luego acceder a él a través de [] o directamente) es, por supuesto, algo artificial, pero debería ilustrar cómo realmente puede acercarse a parcialmente especializando 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) ...
};
 5
Author: Echsecutor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-19 13:05:11

Si necesitas especializar parcialmente un constructor, puedes probar 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 fue anonimizado a partir de algo en lo que estoy trabajando. También puede usar esto cuando tiene una clase de plantilla con muchos y muchos miembros y solo desea agregar una función.

 3
Author: Anonymous Coward,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-04 19:06:55