23 votos

Trucos de plantilla de C++

justo ahora tenía que cavar a través de la página web para averiguar qué clase de plantilla de la plantilla de función miembro estaba dando errores de sintaxis:

template<class C> class F00 {
   template<typename T> bar();
};
...
Foo<C> f;
f.bar<T>(); // syntax error here

Ahora me doy cuenta de que la plantilla de los soportes, son tratados como operadores relacionales. Para hacer lo que era la intención de la siguiente extraña sintaxis es necesario, cf http://stackoverflow.com/questions/1682844/templates-template-function-not-playing-well-with-classs-template-member-functi:

f.template bar<T>();

lo otro extraño aspectos y cayó en la trampa de C++/C++ plantillas que se han encontrado con que no era algo que usted considere a ser de conocimiento común?

14voto

int3 Puntos 6370

Tengo tropezó la primera vez que he heredado de una clase de plantilla de otra clase de plantilla:

template<typename T>
class Base {
    int a;
};

template<typename T>
class Derived : public Base<T> {
    void func() {
        a++; // error! 'a' has not been declared
    }
};

El problema es que el compilador no sabe si Base<T> va a ser la plantilla por defecto o especializado. Una versión especializada no puede tener int a como miembro, por lo que el compilador no puede asumir que está disponible. Pero usted puede decirle al compilador que va a estar allí con el using directiva:

template<typename T>
class Derived : public Base<T> {
    using Base<T>::a;
    void func() {
        a++; // OK!
    }
};

Alternativamente, usted puede hacer explícito el hecho de que usted está usando un miembro de T:

void func {
    T::a++; // OK!
}

8voto

Este me molestó entonces:

#include <vector>
using std::vector;

struct foo {
  template<typename U>
  void vector();
};

int main() {
  foo f;
  f.vector<int>(); // ambiguous!
}

La última línea principal es ambiguo, porque el compilador no sólo se ve hasta vector dentro foo, pero también como un nombre no cualificado a partir de dentro de main. Por lo que se encuentra tanto en std::vector y foo::vector. Para solucionar esto, usted tiene que escribir

f.foo::vector<int>();

GCC no se preocupa de eso, y acepta el código de arriba haciendo la intuitiva cosa (llamar al miembro), otros compiladores de hacerlo mejor y advertir como comeau:

"ComeauTest.c", line 13: warning: ambiguous class member reference -- function
          template "foo::vector" (declared at line 8) used in preference to
          class template "std::vector" (declared at line 163 of
          "stl_vector.h")
        f.vector<int>(); // ambiguous!

5voto

Luc Touraille Puntos 29252

La estrella de preguntas acerca de las plantillas aquí: la falta de typename!

template <typename T>
class vector
{
  public:
    typedef T * iterator;
    ...
};

template <typename T>
void func()
{
    vector<T>::iterator it;           // this is not correct!

    typename vector<T>::iterator it2; // this is correct.
}

El problema aquí es que vector<T>::iterator es dependiente nombre: depende de un parámetro de plantilla. Como consecuencia, el compilador no sabe que iterator designa un tipo; tenemos que decirle a él con la typename de palabras clave.

Lo mismo va para la plantilla de las clases internas o miembro de plantilla/funciones estáticas: se debe eliminar la ambigüedad mediante la template de palabras clave, como se señaló en el OP.

template <typename T>
void func()
{
    T::staticTemplateFunc<int>();          // ambiguous

    T::template staticTemplateFunc<int>(); // ok

    T t;

    t.memberTemplateFunc<int>();          // ambiguous

    t.template memberTemplateFunc<int>(); // ok
}

4voto

navigator Puntos 1005

De la definición de función de miembro de clase de ámbito:

template <typename T> 
class List {                     // a namespace scope class template 
  public: 
	template <typename T2>       // a member function template 
	List (List<T2> const&);      // (constructor) 
	… 
}; 
template <typename T> 
 template <typename T2> 
List<T>::List (List<T2> const& b) // an out-of-class member function 
{                                 // template definition 
	… 
}

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X