Performance :
Dipende.
Nel tuo caso particolare non ci saranno differenze di prestazioni perché i due saranno disposti in modo simile nella memoria.
In un caso molto specifico (se stavi usando una struct vuota come uno dei membri dati) allora std::pair<>
potrebbe potenzialmente utilizzare Empty Base Optimization (EBO) e avere un valore inferiore dimensione dell'equivalente di struct. E le dimensioni inferiori generalmente significano prestazioni più elevate:
struct Empty {};
struct Thing { std::string name; Empty e; };
int main() {
std::cout << sizeof(std::string) << "\n";
std::cout << sizeof(std::tuple<std::string, Empty>) << "\n";
std::cout << sizeof(std::pair<std::string, Empty>) << "\n";
std::cout << sizeof(Thing) << "\n";
}
Stampe: 32, 32, 40, 40 su ideone .
Nota: non sono a conoscenza di alcuna implementazione che utilizza effettivamente il trucco EBO per coppie regolari, tuttavia è generalmente utilizzata per le tuple.
La leggibilità :
Oltre alle micro-ottimizzazioni, tuttavia, una struttura con nome è più ergonomica.
Voglio dire, map[k].first
non è poi così male mentre get<0>(map[k])
è a malapena comprensibile. Contrasto con map[k].name
che indica immediatamente ciò che stiamo leggendo.
È tanto più importante quando i tipi sono convertibili l'uno con l'altro, dal momento che scambiarli inavvertitamente diventa una vera preoccupazione.
Si potrebbe anche voler leggere su Structural vs Nominal Typing. Ente
è un tipo specifico che può essere utilizzato solo da cose che si aspettano Ente
, tutto ciò che può operare su std::pair<std::string, bool>
può operare su di essi ... anche quando std::string
o bool
non contiene cosa si aspettano, perché std::pair
non ha una semantica associata ad essa.
Manutenzione :
In termini di manutenzione, pair
è il peggiore. Non puoi aggiungere un campo.
tuple
è migliore in questo senso, a patto che tu aggiunga al nuovo campo tutti i campi esistenti siano ancora accessibili dallo stesso indice. Che è imperscrutabile come prima ma almeno non è necessario andare e aggiornarli.
struct
è il chiaro vincitore. Puoi aggiungere campi ovunque ti sembrino.
In conclusione:
-
pair
è il peggiore di entrambi i mondi,
-
tuple
può avere un leggero margine in un caso molto specifico (tipo vuoto),
-
utilizza
struct
.
Nota: se usi i getter, puoi usare il trucco base vuoto da solo senza che i client debbano sapere come in struct Thing: Empty { std::string name; }
; che è il motivo per cui Incapsulamento è l'argomento successivo di cui dovresti preoccuparti.