In multiple cases I would want to use something like
template<bool condition>
struct S
{
int value;
if constexpr(condition) /*#if condition*/
double my_extra_member_variable;
/*#endif*/
}
or
if constexpr(sizeof...(Ts) != 0)
// define something extra ( a tuple or so )
This is possible with preprocessor flags, but we want to be the "cool kids" that don't use preprocessor flags, but rather metaprogramming
It could also work with specilizations in some cases, but assume you have multiple conditions, and multiple member variables that need to be conditionally activated, it could get nasty quite fast.
I tried
constexpr in_series_production_mode = false;
struct dummy{ dummy(auto& x){}; operator=(auto& x){return *this;} }; /*1 byte*/
struct debug_data_t { /* lots of parameters with big size*/};
template <typename T>
using maybe_empty = typename std::conditional<in_series_production_mode ,T,dummy>::type;
maybe_empty<debug_data_t> my_debugging_variable;
But with that you still get 1 byte for the unused dummy
variable. While if you used #if
of something similar you would have needed 0 bytes.
Does anybody know a better practice for that?
CodePudding user response:
In C 20, the "good enough" solution is with the [[no_unique_address]]
attribute
struct empty_t {};
template<bool condition>
struct S {
[[no_unique_address]]] std::conditional_t<condition, double, empty_t> var;
};
It's not perfect because var
is always defined, but it will not take any space. Note that if there are multiple variables, you will need them to be different types, e.g.
template<int>
struct empty_t {};
template<bool condition>
struct S {
[[no_unique_address]]] std::conditional_t<condition, double, empty_t<0>> var;
[[no_unique_address]]] std::conditional_t<condition, double, empty_t<1>> rav;
};