Structs without ifdefs in C or C++

Viewed 145

There are some C projects with structs full of ifdefs (for ex. WolfSSL https://github.com/wolfSSL/wolfssl/blob/bb70fee1ecff8945af8179f48e90d78ea7007c66/wolfssl/internal.h#L2792)

struct {
int filed_1;
int field_2;
#ifdef SETTING_A
    int filed_b;
#endif
#ifdef SETTING_B
    int field_b;
#endif
}

The reason is to reduce struct size for unused options. There are a lot of ifdefs! Everywhere!

Is there a C++ way to get rid of those ifdefs, retaining the ability for compiler to optimize out unused fields? Maybe with templates, usings or CRTP inheritance?

1 Answers

You can do it in C++20 with [[no_unique_address]] and some chicanary. This isn't guaranteed result in smaller types however, so I still suggest you use the #defines

template<typename>
struct Empty {};

template<typename T, bool enable, typename uniquer>
using MaybeEmpty = std::conditional_t<enable, T, Empty<uniquer>>;

struct foo {
    int filed_1;
    int field_2;
    [[no_unique_address]] MaybeEmpty<int, settingA, struct filed_b_uniquer> filed_b;
    [[no_unique_address]] MaybeEmpty<int, settingB, struct field_b_uniquer> field_b;
};

Prior to C++20, that would have to be done with base classes

struct with_filed_b {
    int filed_b;
};

struct with_field_b {
    int field_b;
};

struct foo : MaybeEmpty<with_filed_b, settingA, struct filed_b_uniquer>, MaybeEmpty<with_field_b , settingB, struct field_b_uniquer>  {
    int filed_1;
    int field_2;        
};
Related