2011-09-16 36 views
6

Estoy tratando de hacerlo de esta manera:cómo sobrecarga operador << para una matriz en C++?

template <typename T> 
ostream &operator<<(ostream &os, T &arr) 
{ /*...*/ } 

Pero puede T representar una matriz? ¿Es correcto sobrecargar el operador << para una matriz?


EDIT:

De acuerdo con el consejo de kerrek SB, aquí está mi aplicación para <<:

template <typename T, unsigned int N> 
ostream &operator<<(ostream &os, const T (&arr)[N]) 
{ 
    int i; 
    for(i = 0; i < N; i++) 
     os << arr[i] << " "; 
    os << endl; 
    return os; 
} 

¿Es mi aplicación correcta? Tengo un error de compilación.

Respuesta

7

Usted puede hacer esto:

template <typename T, unsigned int N> 
std::ostream & operator<<(std::ostream & os, const T (&arr)[N]) 
{ 
    // .. 
    return os; 
} 

esto sólo funciona para las matrices de tiempo de compilación, por supuesto. Tenga en cuenta que no tiene permiso para crear una instancia de esta plantilla cuando T es un tipo integrado o un tipo en el espacio de nombres std.

Probablemente sea mejor hacer esto en línea si es posible, ya que creará una instanciación separada para cada N. (El pretty printer tiene un ejemplo de esto.)

Usted se dará cuenta, sin embargo, que la plantilla manta introduce una ambigüedad, porque os << "Hello" ahora tiene dos sobrecargas posibles: la plantilla a juego const char (&)[6], y la (no molde) de sobrecarga para el decaimiento a puntero const char *, que tienen secuencias de conversión idénticas. Podemos resolver esto mediante la desactivación de nuestra sobrecarga para arrays de char:

#include <ostream> 
#include <type_traits> 

template <typename T, unsigned int N> 
typename std::enable_if<!std::is_same<T, char>::value, std::ostream &>::type 
operator<<(std::ostream & os, const T (&arr)[N]) 
{ 
    // .. 
    return os; 
} 

De hecho, para ser aún más general también puede hacer las basic_ostream parámetros parámetros de plantilla:

template <typename T, unsigned int N, typename CTy, typename CTr> 
typename std::enable_if<!std::is_same<T, char>::value, 
         std::basic_ostream<CTy, CTr> &>::type 
operator<<(std::basic_ostream<CTy, CTr> & os, const T (&arr)[N]) 
{ 
    // .. 
    return os; 
} 

En vista del hecho de que T debe ser un tipo definido por el usuario, incluso podría reemplazar is_same<T, char> con is_fundamental<T> para obtener un poco más de comprobación (pero los usuarios aún no deben usar esto para matrices de tipos de biblioteca estándar).

+0

gracias, pero yo don ¿No entiendo por qué causa una instanciación separada para cada N si no se implementa en línea? – Alcott

+0

Bueno, es una plantilla, por lo que cada instancia de plantilla puede terminar como una función separada en tu archivo binario. Si está en línea, posiblemente puede evitar la llamada a la función por completo, aunque esto depende del compilador. –

+0

lo tengo.Con este operador << que tiene 2 args de plantilla, ¿cómo podría especificar el segundo arg N? Aparentemente no puedo simplemente usar "cout << ar;" ¿puedo? – Alcott

3

Otra forma en que podría hacer esto sería algo así como lo siguiente:

template<typename T> 
ostream& operator<<(ostream &out, const std::pair<T, int>& array) 
{ 
    //...code 
    return out; 
} 

Dónde T tendrá un puntero a una matriz (es decir, que será el de tipo puntero que la matriz se desintegrará en) , y la parte int del par sería del tamaño de la matriz. A continuación, puede utilizarlo como el siguiente:

int array[10]; 
//...some code that initializes array, etc. 

cout << make_pair(array, 10); 

Una ventaja de este método es que también funciona para matrices dinámicas (es decir, las matrices se puede asignar en el montón, etc.)

+0

Lo intentaré. Gracias – Alcott

+0

Tengo una sensación muy débil de que puede tener problemas con ADL aquí si su 'T' no es un tipo definido por el usuario, aunque no estoy seguro. –

+0

Lo probé con un tipo de compilación como 'int' ... parecía funcionar bien ... No puedo pensar por qué esto entraría en conflicto con las reglas de ADL. Si tiene un objeto 'std :: pair ', la plantilla debería ser capaz de deducir el tipo 'T', y rechazar cualquier instancia utilizando un' std :: pair 'donde' U' no es del tipo 'int' . – Jason

Cuestiones relacionadas