If I want a class with an optional member, I'm using template specialization:
template<class T>
struct X {
T t;
void print() { cout << "t is " << t << '\n'; }
};
template<>
struct X<void> {
void print() { cout << "without T\n"; }
};
This is nice as there is no runtime overhead and little code duplication. However, if I have 3 instead of 1 optional class member, I have to write 2^3=8 classes, that is, the "little duplication" quickly becomes unreasonable.
A possible solution may be to use std::conditional like so:
template<class T1, class T2, class T3>
struct X {
conditional_t<is_void_v<T1>, char, T1> t1;
conditional_t<is_void_v<T2>, char, T2> t2;
conditional_t<is_void_v<T3>, char, T3> t3;
void print() {
if constexpr (!is_void_v<T1>) cout << "t1 is " << t1 << '\n';
if constexpr (!is_void_v<T2>) cout << "t2 is " << t2 << '\n';
if constexpr (!is_void_v<T3>) cout << "t3 is " << t3 << '\n';
}
};
but now, objects of my class waste memory. I'm looking for some way to avoid most of the code duplication (down to at most linear in the number of optional members code overhead) while avoiding to spend more runtime and memory than necessary.
Note that this question exists (with answers) for single optional class members (see Optional class members without runtime overhead, Most efficient way to implement template-based optional class members in C++?) but, to the best of my knowledge, it has not been answered for multiple optional members.