如何将 C 风格的编译时数组转换为 std::array

how to convert C-style compile-time arrays to std::array

在我们的消息来源中,我们经常遇到这样的事情:

static const int g_numbers[]{ 1, 2, 3, 4, 5};
static const struct
{
    const int         m_nID;
    const char* const m_pszName;
}
g_collection[]
{
    { 1, "Max" },
    { 2, "Fabian" },
    { 3, "Martin" },
    …
};

如何将那些编译时数组转换为现代 C++?使用例如std::array?

如果我理解正确,std::array 需要一个大小作为模板参数。

您建议采用哪种方式以最少的开销(例如代码生成)和不必要的冗余信息来转换此类代码?

你有一个选择。要么使用模板参数推导,要么自己指定参数。

使用模板参数推导:

static constexpr std::array g_numbers{1, 2, 3, 4, 5};

struct g_collection_element
{
    int         m_nID;
    char const* m_pszName;
};

static constexpr std::array g_collection{
    g_collection_element{ 1, "Max" },
    g_collection_element{ 2, "Fabian" },
    g_collection_element{ 3, "Martin" },
};

正如你在这里看到的,我命名了结构并在声明后使用它。我还从成员中删除了 const,因为它们在那种情况下并不是很有用。

此外,要使模板参数推导起作用,您必须键入数组中每个初始化程序的元素类型,否则编译器将不会执行模板参数推导。

指定参数:

static constexpr std::array<int, 5> g_numbers{1, 2, 3, 4, 5};

struct g_collection_element
{
    int         m_nID;
    char const* m_pszName;
};

static constexpr std::array<g_collection_element, 3> g_collection{
    { 1, "Max" },
    { 2, "Fabian" },
    { 3, "Martin" },
};

遗憾的是,您不能只指定类型来推导数字。

为了用 C++20 解决方案补充其他答案(尽管有 C++17 上限),您可以使用 std::to_array[=15 来避免一些额外的 elem 提及=]

static constexpr auto g_collection = std::to_array<elem>(
{
    { 1, "Max" },
    { 2, "Fabian" },
    { 3, "Martin" },
});

指定一次elem,大小留待推导。由于明确提供了类型,因此不再需要键入大括号初始值设定项。

这可能看起来像是在创建两个对象(一个临时原始数组和一个静态 std::array),但由于不断求值的好处,它被折叠成一个硬编码对象。