2011-09-16 16 views
6

Sto cercando di fare in questo modo:come operatore di overload << per un array in C++?

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

Ma può T rappresentare un array? È corretto sovraccaricare l'operatore << per un array?


EDIT:

secondo il consiglio di Kerrek SB, ecco la mia implementazione per <<:

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; 
} 

È mia implementazione giusto? Ho ottenuto un errore di compilazione.

risposta

7

Si potrebbe fare questo:

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

Questo funziona solo per gli array in fase di compilazione, naturalmente. Si noti che non è consentito creare un'istanza di questo modello quando T è un tipo incorporato o un tipo nello spazio dei nomi std!

Probabilmente è meglio rendere questo in linea se possibile, poiché si creerà un'istanza separata per ogni N. (Il pretty printer ha un esempio di questo.)

Noterete, però, che il modello di coperta presenta un'ambiguità, perché os << "Hello" ha ora due possibili sovraccarichi: il modello di corrispondenza const char (&)[6], e la (non-modello) sovraccarico per il decay-to-pointer const char *, che hanno entrambe sequenze di conversione identiche. Siamo in grado di risolvere questo disabilitando la nostra sovraccarico per gli array 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; 
} 

In realtà, per essere ancora più generale si può anche fare i basic_ostream parametri parametri di modello:

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; 
} 

In considerazione del fatto che T deve essere un tipo definito dall'utente, è anche possibile sostituire is_same<T, char> con is_fundamental<T> per ottenere un controllo un po 'più (ma gli utenti non devono ancora utilizzare questo per gli array di tipi di libreria standard).

+0

grazie, ma io don capisco perché causa un'istanza separata per ogni N se non implementata in linea? – Alcott

+0

Bene, è un modello, quindi ogni istanza di modello può finire come una funzione separata nel tuo file binario. Se si è in linea, è possibile evitare del tutto la chiamata alla funzione, anche se in definitiva ciò dipende dal compilatore. –

+0

capito.Con questo operatore << con 2 template args, come potrei specificare il secondo arg N? Apparentemente non posso semplicemente usare "cout << ar;", posso? – Alcott

3

Un altro modo si potrebbe fare questo sarebbe qualcosa di simile al seguente:

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

Dove T avrà un puntatore ad un array (ad esempio, sarà il puntatore-tipo che la matrice decadrà in) e la parte della coppia int corrisponderebbe alla dimensione dell'array. È quindi possibile utilizzarlo come il seguente:

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

cout << make_pair(array, 10); 

Uno più con questo metodo è che funziona anche per gli array dinamici (ad esempio, gli array di allocare sul mucchio, etc.)

+0

Ci proverò. Grazie – Alcott

+0

Ho una sensazione molto debole che potresti avere problemi con ADL qui se il tuo 'T' non è un tipo definito dall'utente, sebbene non ne possa essere sicuro. –

+0

L'ho provato con un tipo built-in come 'int' ... sembrava funzionare bene ... Non riesco a pensare perché questo sarebbe in conflitto con le regole ADL. Se si dispone di un oggetto 'std :: pair ', il modello dovrebbe essere in grado di dedurre il tipo' T' e rifiutare qualsiasi istanza utilizzando un 'std :: pair ' dove 'U' non è di tipo' int' . – Jason

Problemi correlati