You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使含可变参数列表的嵌套结构体无需预声明子项即可constexpr初始化?

问题描述

现有如下结构体布局:

#include <vector>
struct A {
    char const* name;
    std::vector<char const*> list;
};

struct B {
    char const* group_name;
    A an_A;
    int other_stuff;
};

初始化方式如下:

B b = {
 "My B",
  { "My A",
    {{ "My", "variable", "length", "list" }}
  },
  42
};

需要找到一种定义方式,让b可以被声明为constexpr,且无需在主项之前声明子项。


尝试用std::initializer_list的问题

修改结构体为使用std::initializer_list以支持constexpr:

#include <initializer_list>

struct A {
    char const* name;
    std::initializer_list<char const*> list;
};

struct B {
    char const* group_name;
    A an_A;
    int other_stuff;
};

B b = {
 "My B",
  { "My A",
    {{ "My", "variable", "length", "list" }}
  },
  42
};

但出现编译错误:

<source>:20:1: error: could not convert '{{"My", "variable", "length", "list"}}' from '<brace-enclosed initializer list>' to 'std::initializer_list<const char*>'
   20 | };
      | ^
      | |
      | <brace-enclosed initializer list>
ASM generation compiler returned: 1
<source>:20:1: error: could not convert '{{"My", "variable", "length", "list"}}' from '<brace-enclosed initializer list>' to 'std::initializer_list<const char*>'
   20 | };
      | ^
      | |
      | <brace-enclosed initializer list>
Execution build compiler returned: 1

错误原因是初始化std::initializer_list时多嵌套了一层大括号,std::initializer_list直接接受单层大括号的元素列表即可。


可行解决方案

1. 修正std::initializer_list初始化(C++11及以上)

去掉多余的大括号,即可正常声明constexpr变量:

#include <initializer_list>

struct A {
    char const* name;
    std::initializer_list<char const*> list;
};

struct B {
    char const* group_name;
    A an_A;
    int other_stuff;
};

constexpr B b = {
 "My B",
  { "My A",
    { "My", "variable", "length", "list" }
  },
  42
};

std::initializer_list在constexpr上下文中会指向编译器生成的只读数组,生命周期与b一致,满足需求。

2. 使用C++20 constexpr std::vector

如果需要完整的容器功能而非仅列表视图,C++20开始std::vector支持constexpr初始化,直接修改原始代码即可:

#include <vector>

struct A {
    char const* name;
    std::vector<char const*> list;
};

struct B {
    char const* group_name;
    A an_A;
    int other_stuff;
};

constexpr B b = {
 "My B",
  { "My A",
    { "My", "variable", "length", "list" }
  },
  42
};

注意需要启用C++20或更高版本的编译标准。

3. 自定义constexpr数组容器(兼容C++11/14)

若需兼容更早的C++标准,可自定义轻量级数组结构体实现可变长度constexpr列表:

template <size_t N>
struct ConstArray {
    char const* data[N];
    constexpr size_t size() const { return N; }
    constexpr char const* operator[](size_t idx) const { return data[idx]; }
};

struct A {
    char const* name;
    ConstArray<0> list;

    template <size_t N>
    constexpr A(char const* n, ConstArray<N> arr) : name(n), list(arr) {}
};

struct B {
    char const* group_name;
    A an_A;
    int other_stuff;
};

constexpr B b = {
 "My B",
  { "My A",
    ConstArray<4>{ "My", "variable", "length", "list" }
  },
  42
};

这种方式在C++11及以上版本中可正常编译,同时保留可变长度列表的constexpr特性。


内容的提问来源于stack exchange,提问作者Adrian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 04:35:29