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

如何构造含不可移动不可复制对象的可指定数量std::array?

问题描述

需要创建一个包含27个不可移动、不可复制对象的数组,后续直接使用对象的引用。

对象定义

class Object {
public:
  explicit Object(std::size_t initial = 1) : value_(initial) {}

  Object(const Object &) = delete;
  Object(Object &&) = delete;
  Object &operator=(const Object &) = delete;
  Object &operator=(Object &&) = delete;

private:
  std::size_t value_;
};

尝试实现及报错

尝试用std::to_array和std::experimental::make_array构造数组,代码如下:

template <size_t... Is>
auto create_semaphores_array_details(size_t concurrency_per_service,
                                 std::index_sequence<Is...> /*unused*/)
{
    return std::to_array(
        {(Is, Object(concurrency_per_service))...});
};

template <size_t amount_of_services>
auto create_semaphores_array(size_t concurrency_per_service)
{
    return create_semaphores_array_details(
            concurrency_per_service,
            std::make_index_sequence<amount_of_services>());
};

constexpr size_t amount_of_services
    = 27;

std::array<Object, amount_of_services>
    semaphores_per_services
    = create_semaphores_array<amount_of_services>(
        5);
  • 使用std::to_array时,报错:is_move_constructible failed
  • 使用std::experimental::make_array时,报错:use of deleted Object(Object &&)

核心问题:如何构造这类数组,同时能灵活修改数组中的对象数量?


解决方案

因为Object既不能复制也不能移动,必须直接在数组的内存空间中原位构造每个对象,不能先创建临时对象再移动/复制。以下是几种简洁可行的方法:

方法1:C++20原位构造法(推荐)

利用std::construct_at直接在std::array的每个元素内存位置上构造对象:

#include <array>
#include <utility>
#include <memory>

template <size_t amount_of_services>
std::array<Object, amount_of_services> create_semaphores_array(size_t concurrency_per_service)
{
    std::array<Object, amount_of_services> arr;
    // 通过索引序列遍历每个位置,原位构造
    auto construct_elements = [&]<size_t... Is>(std::index_sequence<Is...>) {
        (std::construct_at(&arr[Is], concurrency_per_service), ...);
    };
    construct_elements(std::make_index_sequence<amount_of_services>());
    return arr;
}

// 使用示例
constexpr size_t amount_of_services = 27;
std::array<Object, amount_of_services> semaphores_per_services = create_semaphores_array<amount_of_services>(5);

这种方式完全规避了移动/复制操作,直接在数组的内存空间里创建对象,安全高效。

方法2:C++17聚合初始化法

利用折叠表达式和聚合初始化,直接在数组初始化时构造每个元素:

#include <array>
#include <utility>

template <size_t... Is>
auto create_array_impl(size_t val, std::index_sequence<Is...>)
{
    return std::array<Object, sizeof...(Is)>{
        // 借助索引序列展开,每个元素直接原位构造
        (static_cast<void>(Is), Object(val))...
    };
}

template <size_t N>
auto create_semaphores_array(size_t concurrency_per_service)
{
    return create_array_impl(concurrency_per_service, std::make_index_sequence<N>());
}

// 使用示例
constexpr size_t amount_of_services = 27;
std::array<Object, amount_of_services> semaphores_per_services = create_semaphores_array<amount_of_services>(5);

C++17的聚合初始化允许直接在数组元素位置构造不可移动/复制的对象,只要初始化表达式是直接构造而非临时对象转移。

灵活调整数组大小

上述方法都通过模板参数指定数组长度,修改时只需调整模板参数值即可。比如要创建30个对象,只需把constexpr size_t amount_of_services = 30;,再调用create_semaphores_array<30>(5)就行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 07:43:36