【问题标题】:How to create a std::array with std::transform without default constructor如何在没有默认构造函数的情况下使用 std::transform 创建 std::array
【发布时间】:2015-11-17 11:16:29
【问题描述】:

我有一个std::array<Foo, 10>,我想使用从FooBar 的函数创建一个std::array<Bar, 10>。通常我会像这样使用std::transform

array<Bar, 10> bars;
transform(foos.begin(), foos.end(), bars.begin(), [](Foo foo){
    return Bar(foo.m_1, foo.m_2);
});

但是,Bar 没有默认构造函数,因此我无法创建 bars 数组。我总是可以使用vector,但如果能够使用array 来保证我总是有10 个元素,那就太好了。这可能吗?

【问题讨论】:

  • 您可以使用 not-quite-yet-std std::optional 之类的东西来包装 Bar 以用于此数组。至少这不会强制 Bar 通常具有默认构造函数,并且无论如何它都是一个有用的包含在项目中(imo)。
  • 在您的代码中vector.reserve(10) 是否不足以满足10 的大小,或者您是否要确保客户端代码也不会更改该大小?
  • 在这种情况下,vector.reserve 可以正常工作,但这并不重要,因为从语义上讲,这个集合必须有 10 个项目,而且并非在所有情况下都有效。如果我必须将其传递给接受 std::array&lt;Bar, 10&gt;&amp; 的函数,则图像。

标签: c++ c++11 vector std stdarray


【解决方案1】:

std::transform 没有,但没有什么是小模板魔法无法解决的。

template<std::size_t N, std::size_t... Is>
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos,
                                std::index_sequence<Is...>) {
    return {{ Bar(foos[Is].m_1, foos[Is].m_2)... }};
}

template<std::size_t N, std::size_t... Is>
std::array<Bar, N> foos_to_bars(const std::array<Foo, N>& foos) {
    return foos_to_bars(foos, std::make_index_sequence<N>());
}

std::index_sequence 和朋友们是 C++14,但在 C++11 中很容易实现。仅 SO 就可能有六种实现。

【讨论】:

  • 为什么foos_to_bars的return语句中的双括号?它与创建包扩展上下文有关吗?如果是这样,{{ ... }} 是否比您在 SO 中展示的其他人更好(例如 expander)?
  • @NikosAthanasiou Nah,只是消除了一些编译器的“缺少大括号”警告。 (std::array 是一个包含内置数组的聚合;外大括号用于 std::array;内大括号用于内置大括号。您可以省略内大括号,但如果您这样做,一些编译器会发出警告。 )
猜你喜欢
  • 2013-06-07
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 2021-12-29
  • 2010-09-06
  • 1970-01-01
  • 2016-05-31
相关资源
最近更新 更多