2012-03-31 16 views
8

Después de tratar de hacer un poco más fácil el acceso a una clase de almacenamiento, terminé en una situación en la que no tengo mucho conocimiento. Y encontrar personas que intentan hacer lo mismo que yo no es fácil.C++ Plantilla de operador de subíndice de matriz

Lo que estoy tratando de hacer es tener una clase que almacene una matriz de valores como cadenas internamente, pero que permita la conversión de tipos simples desde el extremo del usuario. Lo que había planeado hacer es usar el operador de subíndice de matriz para devolver el tipo que especifiquen a través de una plantilla. Aunque suena mucho mejor de lo que funciona en la práctica. Aquí hay un ejemplo simple de lo que estoy haciendo, para darle una idea de cómo funciona .

class StringList 
{ 
    public: 
    template <typename T> 
    T operator[](const int i) 
} 

A partir de ahí, definiría algunas plantillas específicas, y cualquier usuario podría definir fácilmente más si es necesario. Pero, el mayor problema con esto es que no sé cómo llamar al operador del subíndice con una plantilla. Al principio asumí lo siguiente (que aparentemente no es correcto), considerando que es similar a la forma estándar de llamar a un método de plantilla.

StringList list; 
T var = list<T>[0]; 

¿Alguien sabe la forma correcta de llamar al operador de subíndices como plantilla? O, ¿debería simplemente evitar hacer esto, y usar un método con nombre?

+0

Me gustaría advertir sobre la sobrecarga de 'operator []' para este propósito, ya que los operadores sobrecargados se utilizan mejor cuando tienen significado sintáctico. Normalmente no escribes cosas como 'list [0]', y creo que la sobrecarga intelectual adicional no vale la pena. ¿Por qué no simplemente hacer un método 'get' y llamar a' list.get (0) '? – templatetypedef

+0

@templatetypedef Estoy totalmente de acuerdo. Era más que probable que me quedara con una función nombrada como get, teniendo en cuenta que ni siquiera entiendo cómo escribirías una plantilla como esta. Pero, tengo curiosidad por saber cómo se escribiría, independientemente de si alguna vez necesito usarlo. – TheCodeBroski

Respuesta

10

La única forma de llamar a su operador es escribiendo explícitamente list.operator[]<T>().

Hay dos formas básicas: fuera

  1. Escribe una plantilla de función como list.get<int>() (como propone templatetypedef)
  2. devolver un proxy con la conversación automática a T.

El código se vería así:

// in the class 
struct proxy { 
    proxy(StringList *list, int i) : list(list), i(i) {} 
    StringList *list; 
    int i; 
    template <typename T> 
    operator T() { return list->get<T>(i); } 
}; 

proxy operator[](int i) { return proxy(this, i); } 

template <typename T> 
T get(int i) { return ...; T(); } 

// how to use it: 
StringList list; 
int var = list.get<int>(0); 
float var2 = list[0]; 
+1

Debo admitir que no entiendo muy bien su solución basada en proxy. ¿Te importaría elaborar un poco? ¿Cuál es el propósito de 'T get (int i) {return ...; T(); } '? ¿Cómo es 'proxy operator [] (int i) {return proxy (this, i); } 'relacionado con' StringList'? ¿Cómo funciona la línea 'float var2 = list [0];' work? Mi pequeño conocimiento de las técnicas avanzadas de C++ puede ser la razón aquí. :-) –

4

Creo que no hay una sintaxis para pasar parámetros de plantilla para la llamada natural del operador []. Es probable que necesite llamar:

T var = list.operator[]<T>(0); 

como se hace con las funciones normales de la plantilla, por lo que no hay ningún punto en el uso de la sobrecarga del operador aquí.