Można to zrobić:
template <typename T, unsigned int N>
std::ostream & operator<<(std::ostream & os, const T (&arr)[N])
{
// ..
return os;
}
To działa tylko na tablicach w czasie kompilacji, oczywiście. Zauważ, że nie masz uprawnień do utworzenia tego szablonu, gdy T
jest wbudowanym typem lub typem w przestrzeni nazw std
!
Prawdopodobnie najlepiej zrobić to w linii, jeśli to możliwe, ponieważ spowodujesz oddzielne tworzenie instancji dla każdego N
. (The pretty printer ma tego przykładem.)
Można zauważyć jednak, że szablon koc wprowadza dwuznaczność, gdyż os << "Hello"
ma teraz dwa możliwe przeciążenia: szablon pasujący const char (&)[6]
oraz (non-template) przeciążeniem wskaźnik od zaniku do wskaźnika const char *
, które mają identyczne sekwencje konwersji. Możemy rozwiązać ten problem poprzez wyłączenie naszą przeciążenie dla tablic Znak:
#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;
}
W rzeczywistości, aby być jeszcze bardziej ogólnie można również dokonać basic_ostream
Parametry Parametry szablonu:
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;
}
Ze względu na fakt, że T
musi być typem zdefiniowanym przez użytkownika, można nawet zastąpić is_same<T, char>
przez is_fundamental<T>
, aby uzyskać nieco więcej sprawdzeń (ale użytkownicy nadal nie mogą tego używać w przypadku tablic standardowych typów bibliotek).
Dzięki, ale ja don zrozumieć, dlaczego powoduje on osobne tworzenie instancji dla każdego N, jeśli nie jest zaimplementowane w linii? – Alcott
Cóż, jest to szablon, więc każda instancja szablonu może skończyć jako osobna funkcja w twoim pliku binarnym. Jeśli wbudujesz, możliwe jest całkowite uniknięcie wywołania funkcji, chociaż ostatecznie zależy to od kompilatora. –
rozumiem.Z tym operatorem << posiadającym 2 argumenty szablonu, jak mogę określić drugi argument N? Najwyraźniej nie mogę po prostu użyć "cout << ar;", czy mogę? – Alcott