2015-06-30 22 views
9

Według this answer, poprawny sposób przeciążać operatora wyjściowego << dla tablic C-Style jest to -:Przeciążenie operator wyjścia dla tablic

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

Ale ja wciąż otrzymuję błąd kompilatora

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

dla instrukcji out << "["; i out << "]";.

Jaki jest prawidłowy sposób wykonania tej czynności?

Odpowiedz

8

Problemem jest średnia przeciążenie dla operator<< że drukuje tablicę znaków jest to jedno:

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

Więc gdy podasz swoje:

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

To będzie niejednoznaczna: mamy dwa różne szablony funkcji z identycznymi sekwencjami konwersji, z których żaden nie jest bardziej wyspecjalizowany niż drugi.

Ponieważ jednak chcesz, aby twoja wersja WYŁĄCZNIE nazywała się oryginałem, naprawdę nie ma powodu, aby w ogóle udostępniać swoją wersję. Wystarczy dokonać drukarka „rodzajowe” tablica nie akceptuje char użyciu 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

Czy dbasz o opracowanie dlaczego cytowany odpowiedź nie działa? Czy zmieniono regułę ujednoznaczniania przeciążenia, czy coś zostało wprowadzone, czy też nigdy nie było poprawne? Wygląda dość dziwnie. Twoje podejście jest również ważne dla C++ 11, jeśli zamienisz 'enable_if_t' na mniej przydatne' enable_if', więc myślę, że byłoby to lepsze ogólne podejście, nawet dla drugiego pytania. – luk32

+0

@ luk32 To nigdy nie było poprawne - nie ma powodu, aby preferować jedno przeciążenie nad drugim. – Barry

+0

To było moje przypuszczenie, chociaż wątpię w siebie ponad 200 000 + akceptowanej odpowiedzi użytkownika =). Dzięki za wyjaśnienie. – luk32

Powiązane problemy