简体   繁体   English

在 C++ 中使用语言特性(不是预处理器指令)自动生成大括号括起来的初始化列表

[英]Automatic generation of a brace-enclosed initializer list in C++ using language features (NOT pre-processor directives)

I'm looking for a solution using only native C++ language features (up to C++17) for accomplishing the following:我正在寻找一种仅使用本机 C++ 语言功能(最高 C++17)的解决方案来完成以下任务:

std::array<Type, unsigned int Elem> array_{Type(), // 1    - Call constructor on Type()
                                           Type(), // 2    - ...
                                            ...  , // 3    - ...
                                           Type()} // Elems - Call the Elem:th Type() constructor

In addition, what I'd also like is that each constructor call should be able to take an arbitrary number of arguments.此外,我还想要的是每个构造函数调用应该能够采用任意数量的 arguments。

A concrete example would be to automate the writing of the following:一个具体的例子是自动编写以下内容:

std::array<std::shared_ptr<int>, 4> array_{std::make_shared<int>(),
                                           std::make_shared<int>(),
                                           std::make_shared<int>(),
                                           std::make_shared<int>()}

Ie, provided that I know Type and Elem, I'd like to automate the process of creating the brace-enclosed initializer list and in the process call Type:s constructor.也就是说,如果我知道 Type 和 Elem,我想自动创建大括号括起来的初始化列表的过程,并在这个过程中调用 Type:s 构造函数。

Any ideas?有任何想法吗?

Update, the real problem I'd like to solve is the following:更新,我想解决的真正问题如下:

template <typename Type, unsigned int Size>
class Storage {
  public:
    Storage(std::initializer_list<Type> initializer) : array_{initializer} {}
  private:
    std::array<Type, Size> array_;
};


void foo(){
  Storage<std::shared_ptr<int>, 100> storage(...);

  // or perhaps
  auto storage = std::make_shared<Storage<std::shared_ptr<int>, 100>>(here be an initializer list containing calls to 100 std::make_shared<int>());
}

Like this:像这样:

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

template <std::size_t ...I>
std::array<std::shared_ptr<int>, sizeof...(I)> foo(std::index_sequence<I...>)
{
    return {(void(I), std::make_shared<int>())...};
}

std::array<std::shared_ptr<int>, 4> array_ = foo(std::make_index_sequence<4>());

Guaranteed copy elision from C++17 ensures that the array is constructed in place, and no extra moves happen.来自 C++17 的保证复制省略确保数组是在适当的位置构建的,并且不会发生额外的移动。

The return statement expands to {(void(0), std::make_shared<int>()), (void(1), std::make_shared<int>())...} .返回语句扩展为{(void(0), std::make_shared<int>()), (void(1), std::make_shared<int>())...} void(...) is not strictly necessary, but Clang emits a warning otherwise. void(...)不是绝对必要的,但 Clang 否则会发出警告。


But if it was my code, I'd write a more generic helper instead:但如果是我的代码,我会写一个更通用的帮助程序:

#include <utility>

template <typename R, typename N, typename F, N ...I>
[[nodiscard]] R GenerateForEach(std::integer_sequence<N, I...>, F &&func)
{
    return {(void(I), func(std::integral_constant<N, I>{}))...};
}

template <typename R, auto N, typename F>
[[nodiscard]] R Generate(F &&func)
{
    return (GenerateForEach<R, decltype(N)>)(std::make_integer_sequence<decltype(N), N>{}, std::forward<F>(func));
}

Then:然后:

auto array_ = Generate<std::array<std::shared_ptr<int>, 4>, 4>([](auto){return std::make_shared<int>();});

While the lambda discards the index in this case, it often ends up being useful, especially given that in [](auto index){...} , index.value is constexpr.虽然 lambda 在这种情况下丢弃了索引,但它通常最终还是有用的,特别是考虑到在[](auto index){...}中, index.value是 constexpr。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C++ 默认大括号括起来的初始化列表 - C++ default brace-enclosed initializer list 用大括号括起来的初始化程序列表 - brace-enclosed initializer list 具有预处理程序指令的C ++类生成 - C++ class generation with pre-processor directives C ++自动预处理程序代码生成 - C++ automatic pre-processor code generation C ++ / JNI大括号括起来的初始值设定项映射(Android NDK) - C++ / JNI brace-enclosed initializer Map (Android NDK) 数组必须用大括号括起来的初始化程序 c++ 初始化 - array must be initialized with a brace-enclosed initializer c++ c++ 错误:“数组必须用大括号括起来的初始化器初始化” - c++ error: "array must be initialized with a brace-enclosed initializer" 来自大括号括起的初始值设定项列表的短 C++ 类构造函数 - Short c++ class constructor from brace-enclosed initializer list C++ 中的动态嵌套 arrays 导致无法将大括号括起来的初始值设定项列表转换为 int - Dynamic nested arrays in C++ resulting in cannot convert brace-enclosed initializer list to int C ++函数错误-无法将括号括起来的初始化程序列表转换为char * - C++ Function error — could not convert brace-enclosed initializer list to char*
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM