代码之家  ›  专栏  ›  技术社区  ›  tenfour

如何使用数组元素的索引初始化数组元素

  •  2
  • tenfour  · 技术社区  · 2 年前

    我想找到一种用索引初始化C++数组元素的优雅方法。我有很多这样的代码:

    static constexpr size_t ELEMENT_COUNT = 8;
    MyObject x[ELEMENT_COUNT] = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}};
    

    哪里 MyObject 是有效的,

    struct MyObject {
        size_t mMyIndex;
        MyObject(size_t myIndex) : mMyIndex(myIndex) {}
    };
    

    问题应该已经很清楚:什么时候 ELEMENT_COUNT 更改后,我必须修改初始值设定项列表,这感觉非常不符合C++。如果 元素_计数 例如, 1000 ,这变得不切实际。

    在C++中是否可能出现以下情况

    MyObject mObjects[ELEMENT_COUNT] = initialize_array_with_indices<ELEMENT_COUNT>();
    

    这样的函数像 initialize_array_with_indices<N>() 存在于std库中?有可能吗?使用 std::array<> 是一个选择,如果这能让我更进一步。

    1 回复  |  直到 2 年前
        1
  •  6
  •   user17732522    2 年前

    像这样初始化内置数组是不可能的。数组只能进行默认初始化、值初始化或聚合初始化(字符串文本除外)。其中唯一允许为元素指定不同值的是聚合初始化,这需要显式列出每个元素。

    (还有一个特定于类的非静态数组成员的异常。它们可以通过复制封闭类的隐式定义构造函数来初始化。但是,这仍然不允许像您希望的那样编写初始值设定项。)

    所以你必须使用 std::iota 或初始化后的循环。


    如果您使用 std::array 您可以将其定义为

    template<typename T, std::size_t N>
    constexpr auto initialize_array_with_indices() {
        return []<std::size_t... Is>(std::index_sequence<Is...>){
            return std::array<T, N>{Is...};
        }(std::make_index_sequence<N>());
    }
    

    像这样使用

    auto mObjects = initialize_array_with_indices<MyObject, ELEMENT_COUNT>();
    

    上面的实现需要C++20。它也可以为以前的版本编写(稍长)。特别是在C++20之前,lambdas不能有显式模板参数,因此必须使用helper函数(或 constexpr 可以先用下面的方法填充索引数组,然后 std::apply 用于将索引打包到lambda中)。同样在C++17之前,它将需要复制/移动 T .

    假定默认初始化 MyObject 是可能的,而不是不希望的。(它只是默认初始化 std::数组 然后遍历它以设置索引或使用 标准::iota )