przejście do zawartości
zpr c++ quick reference
Narzędzia użytkownika
Zarejestruj się!
Zaloguj
Narzędzia witryny
Narzędzia
Pokaż stronę
Poprzednie wersje
Odnośniki
Ostatnie zmiany
Menadżer multimediów
Indeks
Zaloguj
Zarejestruj się!
Ostatnie zmiany
Menadżer multimediów
Indeks
Ślad:
tuple
Ta strona jest tylko do odczytu. Możesz wyświetlić źródła tej strony ale nie możesz ich zmienić.
======Biblioteka Boost Tuple====== Czasem w czasie pisania kodu zachodzi potrzeba zgrupowania kilku obiektów w jeden. Biblioteka standardowa implementuje szablon std::pair, który potrafi zgrupować dwa obiekty. Wraz z szablonem funkcji std::make_pair i operatorami porównywania szablon ten tworzy dość przydatne programiście narzędzie. Co w momencie gdy potrzebujemy takiego narzędzia do zgrupowania 3 i więcej wartości? Możemy pokusić się o napisanie własnej klasy bądź szablonu klas grupującego obiekty. O wiele wygodniej jednak skorzystać z gotowego rozwiązania jakie oferuje nam biblioteka Boost Tuple. Oferuje ona szablon boost::tuple pozwalający agregować do 10 elementów. =====Tworzenie krotek===== Do korzystanie z typu boost::tuple niezbędne jest załączenie do programu nagłówka "boost/tuple/tuple.hpp". Aby utworzyć obiekt typu tuple należy podać typ obiektów wchodzących w skład krotki i opcjonalnie listę wartości początkowych o typach zgodnych z typami poszczególnych obiektów tworzących krotkę. <code cpp> /* Tworzymy krotkę o trzech elementach. Wszystkie zostaną zainicjowane zerami. */ boost::tuple<int, int, double> foo; /* Krotka o trzech elementach jawnie zainicjowanych. */ boost::tuple<std::string, double, int> foo("Moja krotka", 29, 5); /* Pozostałe obiekty zostaną zainicjowane domyślnie.*/ boost::tuple<std::string, double, int> foo("Moja krotka"); </code> Jeśli jeden z elementów krotki nie udostępnia konstrukcji domyślnej konieczna jest jawna inicjalizacja. <code cpp> class A //Nasza klasa A { private: A(); //Prywatny konstruktor domyślny public: A(int& i); //Publiczny konstruktor }; boost::tuple<A, A, A, A> foo; //Błąd. Brak konstruktora domyślnego dla klasy A. boost::tuple<A, A, A, A> foo(1, 2, 3, 4); //Poprawne </code> Do tworzenia krotek możemy też użyć funkcji make_tuple, która utworzy krotkę na podstawie dedukcji typów podobnie jak robi to funkcja make_pair dla typu std::pair z biblioteki standardowej. Domyślnie make_tuple określa typy jako niereferencyjne i modyfikowalne (brak const). Jak to zmienić przeczytasz [[tuple#Ciekawostki|tutaj]]. <code cpp> boost::make_tuple(10, "Moja krotka", 10.5); //Tworzy krotkę na podstawie dedukcji typów </code> =====Dostęp do elementów krotki===== Dostęp do elementów krotek możliwy jest dzięki metodzie get klasy tuple lub zewnętrznej wobec klasy funkcji get. Obie wymagają konkretyzacji indeksem elementu (oczywiście liczonym od zera). Obie też zwracają referencję do obiektu znajdującego się pod podanym indeksem. <code cpp> boost::tuple<const int, int, int> foo(10, 20, 30); //Tworzymy krotkę o 3 elementach std::cout<<foo.get<2>(); //Wyświetli 30 std::cout<<boost::tuples::get<2>(foo); //To samo działanie z użyciem zewnętrznej funkcji const int& i=foo.get<0>(); //Dla wartości const lub krotek const zwracana jest referencja const int& j=foo.get<0>(); //Błąd kompilacji std::cout<<foo.get<5>(); //Błąd kompilacji. Rozmiar krotki 3. </code> Użycie zewnętrznej funkcji zamiast metody klasy uzależnia nasz kod od konkretnych nazw obiektów co może być niepożądane w rozwiązaniach uogólnionych. =====Przypisywanie i kopiowanie krotek===== Krotki można przypisywać i kopiować ale tylko jeśli krotka źródłowa i docelowa mają taką samą ilość elementów oraz jeśli elementy krotki źródłowej udostępniają konwersje na odpowiednie typy elementów krotki docelowej. <code cpp> struct A //Klasa bazowa { virtual void fun(){std::cout<<"a";}; }; struct B:public A //Klasa pochodna { virtual void fun(){std::cout<<"b";}; }; boost::tuple<A> ta; //Obiekt klasy bazowej boost::tuple<B> tb; //Obiekt klasy pochodnej ta=tb; //Przypisanie poprawne. Konwersja obiektu klasy pochodnej na obiekt klasy bazowej std::cout<<ta.get<0>().fun(); //Wypisze a. Brak polimorfizmu </code> W skutek konwersji obiektu klasy B na obiekt klasy A utraciliśmy polimorficzne zachowanie. Rozwiązaniem problemu jest przechowywanie w krotkach wskaźników lub referencji do obiektów. <code cpp> /* Hierarchia klas jak w poprzednim przykładzie. */ A a; //Tworzymy obiekt klasy A B b; //Tworzymy obiekt klasy B boost::tuple<A*> ta(&a); //Zamiast obiektu trzymamy wskaźnik do niego boost::tuple<B*> tb(&b); //Zamiast obiektu trzymamy wskaźnik do niego ta=tb; //Przypisanie std::cout<<ta.get<0>()->fun(); //Wypisze "b". Zachowaliśmy polimorfizm. </code> Przykład z referencjami. <code> /* Hierarchia klas jak w poprzednim przykładzie. */ B b; boost::tuple<A&> ta(b); ta.get<0>().fun(); //Wypisze "a". Zachowaliśmy polimorfizm. </code> =====Porównywanie krotek===== Aby porównywać krotki niezbędne jest włączenie do programu nagłówka "boost/tuple/tuple_comparison.hpp". Porównywać możemy tylko krotki o takim samym rozmiarze i jeśli dla odpowiadających elementów są zdefiniowane odpowiednie porównania. Porównanie realizowane są poprzez wywoływanie odpowiednich operatorów parami dla kolejnych obiektów pod odpowiadającymi sobie indeksami. Porównywanie kolejnych par przerywane jest gdy można już ustalić wynik porównania. Operator == zwraca true jeśli wszystkie porównania dla par zwróciły true. Operator != zwraca false gdy chodziaż jedno z porównań zwróciło false. Reszta operatorów realizuje porównania [[http://pl.wikipedia.org/wiki/Porz%C4%85dek_leksykograficzny|leksykograficzne]]. =====Ciekawostki===== Do korzystania z operacji wejścia-wyjścia na krotkach niezbędne jest dołączenie "boost/tuple/tuple_io.hpp". Podział biblioteki Tuple minimalizuje czas kompilacji. Jeśli nie potrzebujemy operatorów relacyjnych czy operacji wejścia-wyjścia nie ponosimy kosztu ich kompilacji.
tuple.1207000426.txt.gz
· ostatnio zmienione: 2008/03/31 23:53 przez
zegadlor
Narzędzia strony
Pokaż stronę
Poprzednie wersje
Odnośniki
Do góry