2010-12-08 9 views

Respuesta

15

El compilador no sabe que A<T>::f() no utiliza el parámetro de tipo T. Entonces, tal como está, debe darle un tipo al compilador cada vez que use f.

Pero cuando estoy diseñando una clase de plantilla y noto que algunos miembros/métodos no dependen de los parámetros de la plantilla, a menudo los moveré a una clase base que no sea la plantilla.

class A_Base { 
public: 
    static void f(); 
}; 

template <class T> class A : public A_Base { 
    // ... 
}; 

Ahora A_Base::f(), A<int>::f() y A<double>::f() realmente son la misma cosa.

+0

+1 para una solución ordenada. Aunque el compilador debería saber si utiliza el parámetro T, si no hay instancias del identificador T en el código, entonces ciertamente no se está utilizando. –

+1

@Billy: Pero si la clase es parte de una biblioteca pública, entonces introducir el uso del parámetro 'T' provocaría un cambio ABI-breaking, ya que' A :: f() 'ya no sería válido. La introducción de contenido en funciones debe * nunca, nunca * romper ABI, solo cambios en la definición de la función. – cdhowie

+1

@Billy ONeal: Sí, excepto cuando 'f()' llama a algunos 'A :: g()' que depende de 'T'. Sin embargo, dado que la regla general es que cualquier cosa relacionada con el uso de un identificador debe depender solo de su declaración, el lenguaje no equivale a 'f ()' con 'f()' aunque 'T' no se use en el cuerpo de 'f '. – jpalecek

1

No: si no desea utilizar un argumento de plantilla, no declare la clase con un parámetro de plantilla. Si necesita el argumento de plantilla para otros miembros de la clase, pero no lo necesita en f, mueva f fuera de la clase.

0

No, en realidad A<int>::f() no es lo mismo de A<any_other_type>::f(). Ellos son realmente diferentes. Si quieres f() a ser realmente independiente del parámetro, puede hacer que la clase de plantilla A a heredar de otra clase (llamada a veces un rasgo) que ofrece f() como una función miembro estática:

struct X 
{ 
    static void f() { ...} 
}; 

template <typename T> 
struct A : X 
{ 
    ... 

A continuación, puede llame al A<type>::f() o X::f().

2
  1. No hay ninguna sintaxis para especificar eso. Hay pocas razones para hacer f un método estático de todos modos. Haga que sea una función gratuita en su lugar. Si debe convertirlo en un método estático por alguna razón, impleméntelo en términos de una función gratuita y simplemente llámelo.
  2. Muchos compiladores probablemente lo hagan automáticamente.
+0

no puedo usar la función libre de estática, porque este no es mi código, solo estoy usando una API ya escrita. Muchas gracias por la respuesta :) –

+0

@Mihran: ¿Eh? ¿Cómo puede una API preocuparse por un método estático? * suspiro * (BILL SMASH STRANGE API! :)) –

1

Sure. Dale un alias asignándolo a un puntero de función.

+1

Por supuesto, igual necesitará "usar" un tipo específico para inicializar ese puntero, como 'typedef void (* func_ptr)(); func_ptr A_f = & A :: f; ' – aschepler

0

Una obra cludgy alrededor (si no desea utilizar la herencia y que no quiere que sea una función no miembro), se puede especificar un tipo predeterminado para su clase:

template <class T = bool> 
class A 
{ 
    public: 
    static void f() { cout << "f()" << endl; } 
}; 

int main(void) 
{ 
    A<>::f(); 
    return 0; 
} 

NOTA: este método, sin embargo es no es el mismo que, A<int>::f() o A<long>::f() etc., pero si usted no tiene ningún tipo de dependencia en la función - a continuación, lo anterior podría funcionar ...

Cuestiones relacionadas