template <typename T, size_t N, typename Allocator>
class small_vector {
union {
static_vector<T, N> inline;
std::vector<T, Allocator> heap;
} storage;
};

.... 🤔

Upside: easiest implementation of my life.

Downside: I have to store the discriminant outside the storage, so I can't know which is which without taking extra space for that.

@thephd Doom: knowing that the discriminator could have fit without adding that extra word of storage will drive you to implement something 100x more complicated and .1% more efficient.
@dgregor79 @thephd I’m increasingly of the opinion that these sorts of small-container optimizations are basically never worth it.
@steve @thephd I think small-string, where you can fit a bunch of ASCII characters in the space of a pointer, is about the only place it makes sense. That, and a free “empty container” representation. Otherwise, nobody picks N well enough and you just wasted code size and stack space.
@dgregor79 @thephd @steve Nah, I bet a lot of them still pay off. Not all, and N is definitely poorly chosen in a lot of cases, but it’s still worthwhile
@dgregor79 @thephd @steve The extra stack usage hurts locality, but the heap is usually worse at locality while *also* adding allocation costs

@rjmccall @dgregor79 @thephd @steve I'm a fan of non-stack uses, where the goal is long-term memory size improvement.

I might be persuaded that there are only two right answers: N=1 and N=<whatever fits in pointer-size storage>, with in-line discriminators.