Performance:
It depends.
In your particular case there will be no performance difference because the two will be similarly laid out in memory.
In a very specific case (if you were using an empty struct as one of the data members) then the std::pair<> could potentially make use of Empty Base Optimization (EBO) and have a lower size than the struct equivalent. And lower size generally means higher performance:
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";
}
Prints: 32, 32, 40, 40 on ideone.
Note: I am not aware of any implementation who actually uses the EBO trick for regular pairs, however it is generally used for tuples.
Readability:
Apart from micro-optimizations, however, a named structure is more ergonomic.
I mean, map[k].first is not that bad while get<0>(map[k]) is barely intelligible. Contrast with map[k].name which immediately indicates what we are reading from.
It's all the more important when the types are convertible to one another, since swapping them inadvertently becomes a real concern.
You might also want to read about Structural vs Nominal Typing. Ente is a specific type that can only be operated on by things that expect Ente, anything that can operate on std::pair<std::string, bool> can operate on them... even when the std::string or bool does not contain what they expect, because std::pair has no semantics associated with it.
Maintenance:
In terms of maintenance, pair is the worst. You cannot add a field.
tuple fairs better in that regard, as long as you append the new field all existing fields are still accessed by the same index. Which is as inscrutable as before but at least you don't need to go and update them.
struct is the clear winner. You can add fields wherever you feel like it.
In conclusion:
pair is the worst of both worlds,
tuple may have a slight edge in a very specific case (empty type),
- use
struct.
Note: if you use getters, then you can use the empty base trick yourself without the clients having to know about it as in struct Thing: Empty { std::string name; }; which is why Encapsulation is the next topic you should concern yourself with.
std::pairis a struct.std::pairis a template.std::pair<string, bool>is a struct.pairis entirely devoid of semantics. Nobody reading your code (including you in the future) will know thate.firstis the name of something unless you explicitly point it out. I am a firm believer in thatpairwas a very poor and lazy addition tostd, and that when it was conceived nobody thought "but some day, everybody is going to use this for everything that is two things, and nobody will know what anybody's code means".mapiterators aren't valid exceptions. ("first" = key and "second" = value... really,std? Really?)