I have a templated struct that has a variant with an extra float, like this:
template <bool HasFloat>
struct Foo {
std::vector<int> a;
float b; // Not needed if HasFloat is false
};
To save memory (yes it is significant) I'd like to omit that float if HasFloat
is false. Since there is a lot of other stuff in the struct
the best way would be something like this:
using B = typename std::conditional<HasFloat, float, ZeroSizedType>::type;
B b;
Except there is no such thing as a zero sized type in C++ as far as I can tell. The only exception seems to be "Flexible Array Members", so I could maybe do something like this:
using B = typename std::conditional<HasFloat, float, float[]>::type;
Except they are only supported in C99, not C++.
The standard solution to this seems to be to use inheritance, since base classes can be zero-sized, however my struct is also accessed by assembly and to make the assembly simpler it is better if the float b;
is at the end of the struct rather than the beginning, and anyway that isn't guaranteed.
So this seems to leave template specialisation as the only option but my class is actually rather long and I'd like to avoid duplicating everything. Is there another solution that I'm missing?
[[no_unique_address]]
attribute to allow an empty struct member to have zero size. – aschepler