0

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?

1 Answers1

4

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;
};
Passer By
  • 19,325
  • 6
  • 49
  • 96
  • Great idea, thanks ...^^ .. Does it have to be `empty_t` ? Would it work with `empty` with no templates as well? – Ahmed Mahrous Mar 09 '22 at 13:26
  • "*if there are multiple variables, you will need them to be different types*" - why? – Remy Lebeau Mar 09 '22 at 17:00
  • @RemyLebeau It's a simplification. `no_unique_address` actually means "maybe no unique address if the types involved are different". Two objects of the same type having the same address is the same object. That can't happen, so they have different addresses. – Passer By Mar 10 '22 at 04:47
  • @PasserBy [according to this](https://en.cppreference.com/w/cpp/language/attributes/no_unique_address), the types don't matter at all, only the names. – Remy Lebeau Mar 10 '22 at 16:00
  • @RemyLebeau See the comments in the example. Also notice how it's worded "need not", as in the attribute isn't a strict requirement. The compiler can in fact ignore the attribute completely. – Passer By Mar 10 '22 at 16:44