Różnica między std :: pair a std :: tuple z tylko dwoma elementami?

92

Czy jest jakaś różnica między a std::paira, gdy std::tuplema tylko dwóch członków? (Poza oczywistym, że std::pairwymaga dwóch i tylko dwóch członków i tuplemoże mieć mniej więcej ...)

Casey
źródło

Odpowiedzi:

86

Istnieje kilka różnic:

  1. std::tuplenigdy nie może być według układu standardowego (przynajmniej nie jest to wymagane przez standard). Każdy std::pair<T, Y>jest układem standardowym, jeśli oba Ti Ysą układem standardowym.

  2. Trochę łatwiej jest uzyskać zawartość a pairniż a tuple. Musisz użyć wywołania funkcji w tupleprzypadku, gdy pairsprawa jest tylko polem składowym.

Ale to jest o tym.

Nicol Bolas
źródło
5
„Trochę łatwiej jest wyciągnąć dane z pary niż z krotki. Trochę”. Zauważyłem. : P Chociaż .firsti .secondsą przydatne, nie oferują żadnej pomocy, jeśli trzeci (lub więcej) członek jest wymagany w zmianie kodu. Zauważyłem, że zwykle używam std::getniezależnie od jakichkolwiek Gettersów, w ten sposób nie muszę zmieniać wszystkiego, tylko typy danych i wszelkie make_pairwywołania make_tuplewywołań.
Casey,
Wygląda na to, że std::mapużywa std::pair<const Key,T>jako value_typeparzysty w C ++ 11. Gdzie dokładnie są używane krotki std::map?
nknight
@nknight: ... Nie mam pojęcia, dlaczego to powiedziałem. Albo to, co chciałem powiedzieć zamiast std::map.
Nicol Bolas
1
@Yakk: Hm, naciskam „.” a moje IDE wyświetla listę członków. Nie sądziłem, że ludzie tego potrzebują.
Nicol Bolas
2
Zastanawiam się, czy strukturalne powiązanie w c ++ 17 już unieważnia zarówno 1, jak i 2 punkt tej odpowiedzi? Jeśli tak, dodaj również wersję C ++ 17.
sandthorn
29

Jest to bardzo późna odpowiedź, ale zwróć uwagę, że ponieważ std::pairjest zdefiniowana za pomocą zmiennych składowych, jego rozmiaru nie można zoptymalizować przy użyciu optymalizacji pustej klasy bazowej ( firsti secondmusi zajmować odrębne adresy, nawet jeśli jedna lub obie są pustymi klasami). Pogarsza to wszelkie wymagania dotyczące dopasowania second_type, więc w najgorszym przypadku wynik std::pairbędzie zasadniczo dwukrotnie większy niż powinien.

std::tuplezezwala na dostęp tylko przez funkcje pomocnicze, więc jest możliwe, aby wywodził się z dowolnego typu, jeśli jeden lub drugi jest pusty, oszczędzając na narzutach. Implementacja GCC przynajmniej zdecydowanie to robi ... możesz przejrzeć nagłówki, aby to sprawdzić, ale jest też to jako dowód.

Stephen Lin
źródło
4
Oczywiście C ++ 20[[no_unique_address]] powinien usunąć tę std::pairwadę.
Deduplicator
„std :: tuple zezwala na dostęp tylko przez funkcje pomocnicze” lub strukturalne powiązania C ++ 17. Smutne, że tak wiele rozsądnych odpowiedzi w C ++ jest obecnie tak szybko nieaktualnych. :-(
cosimo193
29

std::tupleName „s jest dłuższy (jeden dodatkowy znak). Więcej tych znaków jest wpisywanych prawą ręką, więc większości ludzi jest to łatwiejsze do wpisania.

To powiedziawszy, std::pairmoże mieć tylko dwie wartości - nie zero, jeden, trzy lub więcej. DWIE wartości. Jednak krotka nie ma prawie żadnego ograniczenia semantycznego co do liczby wartości. W std::pairzwiązku z tym bardziej dokładny jest bezpieczny typ, którego można użyć, jeśli faktycznie chcesz określić parę wartości.

Arafangion
źródło
20
LOL! Wspaniale, że zastanawiasz się, jak to jest napisane! Chciałbym jednak zaznaczyć, że prawdopodobnie wpisuję „para” ponad 20% szybciej niż „krotka”. Dzieje się tak, ponieważ moje ręce naprzemiennie wpisują każdy znak, tj. RHS: p, LHS: a, RHS: i, LHS: r. Przynajmniej dla mnie jest to łatwiejsze do zrobienia! - ale nadal otrzymujesz +1!
Richard Corden
15
Dlatego para std :: jest dokładniejszym typem bezpiecznym do użycia, jeśli faktycznie chcesz określić parę wartości. ” Nie jest bardziej bezpieczny dla typu ani „dokładny”, a jedynie (prawdopodobnie) sygnalizuje zamiar bardziej bezpośrednio.
ildjarn
1
@Arafangion: std::tuple<>jest również bezpieczny dla typów (jak mogłoby to nie być?) I 2nie różni się semantycznie od pair.
ildjarn
1
Std :: pair jest zatem dokładniejszym typem bezpiecznym w użyciu ” I myślę, że każdy mówiący po angielsku będzie myślał o „parze” i „dwóch” jako o całkowicie synonimach. : -]
ildjarn
5
@ildjam: Dzielimy tutaj włosy, ale nie, nie są one całkowicie synonimami. Kiedy mówisz „dwa buty”, masz na myśli „dwa buty, które mogą być obydwoma lewymi butami”, czy „parę butów” (z których jeden jest zawsze lewy, a drugi zawsze prawy) ?
Arafangion
9

Zauważ, że w C ++ 17 można używać tego samego interfejsu do odczytywania danych zarówno z pary, jak i krotki z dwoma elementami.

auto [a, b] = FunctionToReturnPairOrTuple();

Nie ma potrzeby używania get<>:)

bhardwajs
źródło
3

Co jest warte, uważam, że wyjście GDB std :: tuple jest znacznie trudniejsze do odczytania. Oczywiście, jeśli potrzebujesz więcej niż 2 wartości, wtedy std :: pair nie zadziała, ale uważam to za punkt na korzyść struktur.

tgoodhart
źródło
Dlatego kiedy używam ich w klasach, zawijam linię brutto std::get<0>(tupleName)geterem; GetX()jest dużo łatwiejszy do odczytania i krótszy. Ma małą wadę, że jeśli zapomnisz, aby to constsposób ktoś może zrobić coś głupiego tak: GetX() = 20;.
Casey