tipos template programacion plantillas funciones cabecera ats archivos c++ templates specialization

programacion - template en c++ pdf



¿Cómo puedo obtener una plantilla especializada para usar la versión no especializada de una función miembro? (3)

Considera el siguiente código:

template <int dim> struct vec { vec normalize(); }; template <> struct vec<3> { vec cross_product(const vec& second); vec normalize(); }; template <int dim> vec<dim> vec<dim>::normalize() { // code to normalize vector here return *this; } int main() { vec<3> direction; direction.normalize(); }

Compilar este código produce el siguiente error:

1> main.obj: error LNK2019: símbolo externo no resuelto "public: struct vec <3> __thiscall vec <3> :: normalize (void)" (? Normalizar @? $ Vec @ $ 02 @@ QAE? AU1 @ XZ) referenciado en la función _main


No puedes :) Lo que quieres es especializar las funciones miembro en su lugar:

template <int dim> struct vec { // leave the function undefined for everything except dim==3 vec cross_product(const vec& second); vec normalize(); }; template<> vec<3> vec<3>::cross_product(const vec& second) { // ... } template <int dim> vec<dim> vec<dim>::normalize() { // code to normalize vector here return *this; }

Otra solución un poco más complicada es usar boost::enable_if :

template <int dim> struct vec { // function can''t be called for dim != 3. Error at compile-time template<int dim1> typename boost::enable_if_c< dim == dim1 && dim1 == 3, vec<dim1> >::type cross_product(const vec<dim1>& second) { // ... } vec normalize(); // delegate to the template version void without_params() { // delegate this->without_params<dim>(); } private: // function can''t be called for dim != 3. Error at compile-time template<int dim1> typename boost::enable_if_c< dim == dim1 && dim1 == 3 >::type without_params() { // ... } }; template <int dim> vec<dim> vec<dim>::normalize() { // code to normalize vector here return *this; }

Eso causará un error de tiempo de compilación si cross_product se llama para cualquier dim! = 3. Tenga en cuenta que ese ''truco'' solo funciona para funciones con parámetros, ya que solo entonces el parámetro de la plantilla se puede deducir automáticamente. Para casos sin parámetros, he proporcionado una función sin parámetros arriba :).


No ha proporcionado una definición de vec <3> :: normalize, por lo que obviamente el enlazador no puede vincularlo.

Todo el punto en una especialización de plantilla es que puede suministrar versiones especializadas de cada método. Excepto que en realidad no haces eso en este caso.


Por lo que sé, no puedes llamar a la versión "genérica".

Alternativamente, puede definir sus implementaciones genéricas fuera de las clases como funciones:

template <int dim> struct vec { }; namespace impl { template <int dim> vec<dim> normalize(const vec<dim>& v) { // code to normalize vector here return v; } } template <> struct vec<3> { vec cross_product(const vec& second); vec normalize() { return impl::normalize(*this); } }; int main() { vec<3> direction; direction.normalize(); }