2015-06-30 15 views
9

Secondo this answer, il modo corretto di sovraccaricare operatore di output << per gli array C-style è questo -:sovraccarico operatore di output per gli array

#include <iostream> 
using namespace std; 

template <size_t arrSize> 
std::ostream& operator<<(std::ostream& out, const char(&arr)[arrSize]) 
{ 
    return out << static_cast<const char*>(arr); // use the original version 
} 

// Print an array 
template<typename T1, size_t arrSize> 
std::ostream& operator <<(std::ostream& out, const T1(& arr)[arrSize]) 
{ 
    out << "["; 
    if (arrSize) 
    { 
     const char* separator = ""; 
     for (const auto& element : arr) 
     { 
      out << separator; 
      out << element; 
      separator = ", "; 
     } 
    } 
    out << "]"; 
    return out; 
} 

int main() 
{ 
    int arr[] = {1, 2, 3}; 
    cout << arr; 
} 

Ma ancora sto ottenendo l'errore del compilatore

error: ambiguous overload for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'const char [2]') 

per le dichiarazioni out << "["; e out << "]";.

Qual è il modo corretto di farlo?

risposta

8

Il problema è il sovraccarico di standard per operator<< che stampa un array di caratteri è questo:

template< class CharT, class Traits > 
basic_ostream<CharT,Traits>& operator<<(basic_ostream<CharT,Traits>& os, 
             const char* s); 

Quindi, quando si fornisce la vostra:

template <size_t arrSize> 
std::ostream& operator<<(std::ostream& out, const char(&arr)[arrSize]) 

che sta per essere ambiguo: abbiamo due diversi modelli di funzioni con sequenze di conversione identiche, nessuno dei quali è più specializzato dell'altro.

Tuttavia, dal momento che si desidera che la propria versione JUST chiami l'originale, non c'è davvero alcun motivo per fornire la propria versione. Basta fare la stampante serie "generico" non accetta char utilizzando SFINAE:

// Print an array 
template<typename T1, size_t arrSize, 
     typename = std::enable_if_t<!std::is_same<T1,char>::value>> 
std::ostream& operator <<(std::ostream& out, const T1(& arr)[arrSize]) 
{ /* rest as before */ } 
+0

Ti andrebbe di approfondire il motivo per cui la risposta citato non funziona? È stata modificata qualche regola di disambiguazione del sovraccarico o è stata introdotta una soluzione oppure non è mai stata corretta? Sembra piuttosto strano Il tuo approccio è valido anche per C++ 11, se scambi 'enable_if_t' per il meno utile' enable_if', quindi immagino che sarebbe un approccio migliore in generale, anche per l'altra domanda. – luk32

+0

@ luk32 Non è mai stato corretto: non c'è motivo di preferire un sovraccarico all'altro. – Barry

+0

Questa era la mia ipotesi, anche se tendo a dubitare di me stesso più di 200k + risposta accettata dall'utente =). Grazie per il chiarimento. – luk32