70

I've checked all major compilers, and sizeof(std::tuple<int, char, int, char>) is 16 for all of them. Presumably they just put elements in order into the tuple, so some space is wasted because of alignment.

If tuple stored elements internally like: int, int, char, char, then its sizeof could be 12.

Is it possible for an implementation to do this, or is it forbidden by some rule in the standard?

Daniel Langr
  • 18,256
  • 1
  • 39
  • 74
geza
  • 26,117
  • 6
  • 47
  • 111
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/198907/discussion-on-question-by-geza-stdtuple-sizeof-is-it-a-missed-optimization). – Samuel Liew Sep 04 '19 at 00:28
  • 2
    related: [Is there a GCC keyword to allow structure-reordering?](https://stackoverflow.com/q/14671253/995714), [Can a C++ compiler re-order elements in a struct](https://stackoverflow.com/q/916600/995714), [Why doesn't GCC optimize structs?](https://stackoverflow.com/q/118068/995714), [Automated field re-ordering in C structs to avoid padding](https://stackoverflow.com/q/867471/995714) – phuclv Sep 04 '19 at 01:06
  • @phuclv: There's a big difference between a `struct` and a `tuple` => one is a language construct, the other a library type. Why would you think that they must obey the same rules? – Matthieu M. Sep 04 '19 at 19:47
  • @MatthieuM. where did I say that they obey the same rules? – phuclv Sep 05 '19 at 01:28
  • @phuclv: Then what is the point of the related questions? If they obey different rules, looking at the rules for struct does not help. – Matthieu M. Sep 05 '19 at 09:10

3 Answers3

59

std::tuple sizeof, is it a missed optimization?

Yep.

Is it possible for an implementation to do this[?]

Yep.

[Is] it forbidden by some rule in the standard?

Nope!

Reading through [tuple], there is no constraint placed upon the implementation to store the members in template-argument order.

In fact, every passage I can find seems to go to lengths to avoid making any reference to member-declaration order at all: get<N>() is used in the description of operational semantics. Other wording is stated in terms of "elements" rather than "members", which seems like quite a deliberate abstraction.

In fact, some implementations do apparently store the members in reverse order, at least, probably simply due to the way they use inheritance recursively to unpack the template arguments (and because, as above, they're permitted to).

Speaking specifically about your hypothetical optimisation, though, I'm not aware of any implementation that doesn't store elements in [some trivial function of] the user-given order; I'm guessing that it would be "hard" to come up with such an order and to provide the machinery for std::get, at least as compared to the amount of gain you'd get from doing so. If you are really concerned about padding, you may of course choose your element order carefully to avoid it (on some given platform), much as you would with a class (without delving into the world of "packed" attributes). (A "packed" tuple could be an interesting proposal…)

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/199001/discussion-on-answer-by-lightness-races-in-orbit-stdtuple-sizeof-is-it-a-miss). – Samuel Liew Sep 05 '19 at 11:18
15

Yes, it's possible and has been (mostly) done by R. Martinho Fernandes. He used to have a blog called Flaming Danger Zone, which is now down for some reason, but its sources are still available on github.

Here are the all four parts of the Size Matters series on this exact topic: 1, 2, 3, 4.

You might wish to view them raw since github doesn't understand C++ highlighting markup used and renders code snippets as unreadable oneliners.

He essentially computes a permutation for tuple indices via C++11 template meta-program, that sorts elements by alignment in non-ascending order, stores the elements according to it, and then applies it to the index on every access.

yuri kilochek
  • 11,212
  • 2
  • 25
  • 52
  • 1
    Thanks, I'll check this out. A better way would be to sort by alignment (instead of size). – geza Sep 03 '19 at 15:38
  • @geza my bad, he does actually sort by alignment. – yuri kilochek Sep 03 '19 at 15:39
  • Note that this says nothing about whether the standard `tuple` is permitted to work this way. So, although it's very interesting, it doesn't really answer the question – Lightness Races in Orbit Sep 03 '19 at 15:43
  • 4
    The site is up and "running" but it seems to have been taken over by a domain squatter running a phishing attack. Tells me I've won 1 out of 100 tablet computers if I tell them my google password or something. – Damon Sep 04 '19 at 10:26
-4

Another reason not to: some architectures, including x86, have an indexing mode that can address an address base + size × index in a single instruction—but only when size is a power of 2. Or it might be slightly faster to do a load or store aligned to a 16-byte boundary. This could make code that addresses arrays of std::tuple slightly faster and more compact if they add four padding bytes.

Davislor
  • 12,287
  • 2
  • 26
  • 36