【问题标题】:Structs without ifdefs in C or C++C 或 C++ 中没有 ifdef 的结构
【发布时间】:2021-11-12 08:54:42
【问题描述】:

有些 C 项目的结构中充满了 ifdef(例如 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
}

原因是为了减少未使用选项的结构大小。 有很多ifdef!无处不在!

有没有一种 C++ 方法可以摆脱那些 ifdef,保留编译器优化未使用字段的能力? 也许使用模板、使用或 CRTP 继承?

【问题讨论】:

  • 您正在查看一个 C 项目。在这方面,在 C 中不可能有太多的事情。在 C++ 中,您可以只使用(多重)继承。
  • С++ 继承使用虚拟指针表,因此会影响性能。此外,这种方法需要 2 个设置有 4 个不同的类。如果我有 10 个设置怎么办?
  • 继承并不意味着 vtable
  • 即使如果你能够做到这一点,代码的所有用户仍然需要在编译时检查 field_a 和 field_b 是否存在。
  • @XeenychXeenych 没有虚拟成员的结构没有虚拟开销

标签: c++ c struct


【解决方案1】:

You can do it in C++20[[no_unique_address]] 和一些诡计。然而,这并不能保证导致较小的类型,所以我仍然建议您使用#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;
};

在 C++20 之前,必须使用基类来完成

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;        
};

【讨论】:

  • 看起来不错。旧的 C++ 怎么样?
  • @XeenychXeenych 在此之前,让空对象不占用空间的唯一方法是将它们作为基础子对象
  • 您能举个例子吗?
  • @GuillaumeRacicot 哎呀,已修复
猜你喜欢
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 2021-08-29
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 2018-03-13
  • 2019-02-10
相关资源
最近更新 更多