C++中使用花括号初始化具有固定大小数组成员的结构体

3

Consider the following struct:

struct IPv6Address {
    uint8_t x[16];

    uint8_t& operator[](size_t pos) { return x[pos]; }
    uint8_t* bytes() { return x; }
}

static const IPv6Address WELL_KNOWN_ADDRESS =       //ff02::1
    {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};

这样的大括号初始化是有效的。但是一旦我添加了构造函数,大括号初始化就不再起作用了。我希望在保留大括号初始化的同时也能使用这个构造函数:

IPv6Address(uint8_t bytes[16]) { memcpy(x, bytes, sizeof(x)); }

显然,一旦我添加了自己的构造函数,就不再隐式定义任何构造函数。但是,在这种情况下,如何重新定义花括号初始化或强制编译器创建所有默认构造函数呢?
额外要求:由于我正在为嵌入式应用程序编程,因此无法使用stdlib。

我认为你做不到。你考虑过编写一个免费函数来为你构建结构体吗? - Max Langhof
3
另一个考虑因素:使用IPv6Address = std::array<uint8_t, 16>; - Max Langhof
@MaxLanghof 为什么你不能做到呢?IPv6Address(std::initializer_list<uint8_t>)难道不是OP想要的吗? - Algirdas Preidžius
改用 IPv6Address(uint8_t const bytes[16]),而非 IPv6Address(uint8_t bytes[16])。对于索引也是如此:通常支持 const 是个好主意。 - Cheers and hth. - Alf
我忘了提到我不能使用stdlib,因为我正在为嵌入式应用程序编程。但是由于该功能似乎是核心语言的一部分,重新定义该行为应该是可能的... - J. Hamme
2个回答

2
您可以在现有的构造函数中使用双括号列表(当不允许使用initialiter_list时)。
static const IPv6Address WELL_KNOWN_ADDRESS =  
{{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};

1

使用带有initializer_list的构造函数

以下构造函数应该可以胜任(未测试).

IPv6Address(std::initializer_list<uint8_t> c) : x{} {
  assert(c.size() <= std::size(x));
  std::copy(c.begin(), c.end(), x);
}

你应该添加成员初始化器 : x{},这样如果提供的列表较小,则剩余的元素将被初始化为零。 - NathanOliver
很遗憾,我不能使用stdlib,因为我正在为嵌入式应用程序编程。 - J. Hamme
@J.Hamme 如果是这样的话,请考虑阅读这篇文章:https://stackoverflow.com/questions/34366355/how-to-keep-the-implicitly-declared-aggregate-initialization-constructor - Algirdas Preidžius
@Algirdas Preidžius 谢谢你提供的链接!我现在添加了一个静态的 IPv6Address fromBytes( const uint8_t* bytes ) 方法。这解决了我的问题,因为 IPv6Address 仍然是一个聚合体。 - J. Hamme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接