Miałem problem z opisem opisanym w this question (deklarowanie funkcji szablonu jako znajomego klasy szablonu) i uważam, że druga odpowiedź jest tym, co chcę zrobić (przesyła dalej szablon funkcja, następnie nazwij specjalizację jako przyjaciela). Mam pytanie, czy nieco inne rozwiązanie jest rzeczywiście poprawna lub po prostu zdarza się pracować w Visual C++ 2008.Funkcja przyjaciela szablonu szablonu klasy
kod testu jest:
#include <iostream>
// forward declarations
template <typename T>
class test;
template <typename T>
std::ostream& operator<<(std::ostream &out, const test<T> &t);
template <typename T>
class test {
friend std::ostream& operator<< <T>(std::ostream &out, const test<T> &t);
// alternative friend declaration
// template <typename U>
// friend std::ostream& operator<<(std::ostream &out, const test<T> &t);
// rest of class
};
template <typename T>
std::ostream& operator<<(std::ostream &out, const test<T> &t) {
// output function defined here
}
Najpierw jedna dziwna rzecz znalazłem było to, że jeśli zmienię przednia deklaracja operator<<
, tak aby się nie zgadzała (na przykład, std::ostream& operator<<(std::ostream &out, int fake);
, wszystko nadal się kompiluje i działa poprawnie (dla jasności, nie muszę definiować takiej funkcji, tylko ją deklaruję) .Jednak jak w połączone z pytaniem, usunięcie deklaracji forward powoduje problem, ponieważ wydaje się, że kompilator deklaruje element danych zamiast funkcji znajomego. Jestem prawie pewien, że to zachowanie jest błąd Visual C++ 2008.
Ciekawostką jest usunięcie oświadczeń typu "forward" i użycie alternatywnej deklaracji znajomego w powyższym kodzie. Zauważ, że parametr szablonu U
nie pojawia się w następującym sygnaturze. Ta metoda również kompiluje i działa poprawnie (bez zmiany czegokolwiek innego). Moje pytanie brzmi, czy jest to zgodne ze standardem, czy idiosynkrazą programu Visual C++ 2008 (nie mogłem znaleźć dobrej odpowiedzi w moich podręcznikach).
pamiętać, że deklaracja przyjaciel template <typename U> friend ... const test<U> &t);
działa również, to rzeczywiście daje każdemu wystąpienie operator friend
dostępu do jakiejkolwiek instancji test
, natomiast to, co chcę jest, że prywatne członkowie test<T>
powinny być dostępne tylko z operator<< <T>
. Przetestowałem to, tworząc instancję test<int>
wewnątrz operator<<
i uzyskując dostęp do prywatnego elementu; powinno to spowodować błąd kompilacji podczas próby wyprowadzenia test<double>
.
Streszczenie: Usunięcie deklaracji forward i przejście na alternatywną deklarację przyjaciela w powyższym kodzie wydaje się dawać taki sam wynik (w Visual C++ 2008) - czy ten kod jest rzeczywiście poprawny?
AKTUALIZACJA: Każda z powyższych modyfikacji kodu nie działa w gcc, więc domyślam się, że są to błędy lub "cechy" kompilatora Visual C++. Wciąż doceniam spostrzeżenia od osób znających standard.
Nawiasem mówiąc, doszedłem do wniosku, że dodanie 'using namespace std;' zanim deklaracja klasy usunie potrzebę deklaracji forward, co jak przypuszczam jest efektem ubocznym (możliwego) błędu kompilatora. –
Zgodnie z moim komentarzem - czy możesz wyraźnie dodać przykłady (w tym tworzenie instancji), o których mówisz, że działają? Werbalnie trudno jest zrozumieć, co masz na myśli dla każdego przykładu. –