c++ - 是否有一种可扩展的方法来从 C++ 中的数组初始化结构?
问题描述
struct SomeStruct {
int a;
int b;
int c;
int d;
};
void main() {
std::array<int, 4> arr {1, 2, 3, 4};
SomeStruct someStruct { ??? }; // <------ Initialize with arr? (Ideal would be {arr})
}
如代码示例所示,是否有一些快捷方式可以使用 arr 初始化 someStruct?而不是诉诸:
SomeStruct someStruct {arr[0], arr[1], arr[2], arr[3]};
解决方案
您可以使用std::apply
创建参数包并在初始化程序中使用它:
auto someStruct = std::apply([](auto&&... args){return SomeStruct{decltype(args)(args)...};}, arr);
你可以把它放在一个函数中以便舒适地使用它:
template<typename T, typename A>
constexpr T make_from_tuple_list_init(A&& a) {
return std::apply([](auto&&... args){return T{decltype(args)(args)...};}, std::forward<A>(a));
}
然后将其用作
auto someStruct = make_from_tuple_list_init<SomeStruct>(arr);
这需要 C++17 和#include<tuple>
,但也可以在早期的 C++ 版本中实现(需要更多的努力)。同样在 C++17 中,这保证使用复制省略,因此只会SomeStruct
构造一个。在 C++17 之前,可能会涉及一些移动构造(尽管编译器已经被允许并且确实实现了具有相同效果的返回值优化)。
std::apply
还有一个好处是它适用于实现std::get
和的每种类型std::tuple_size
,这意味着它将适用于例如std::array
、std::tuple
和std::pair
具有该接口的其他用户定义类型。
有人可能想要制作这个函数的两个版本,一个使用T{...}
如上,一个使用T(...)
,以便一个能够在列表初始化和直接初始化之间进行选择。
但是,T(...)
自 C++17 起,该版本已在标准库中实现为std::make_from_tuple
. 在 C++20 中,聚合初始化也可以使用括号,因此std::make_from_tuple
可以直接用于您的情况。
对于 C++14 实现,请从cppreference 的页面中std::make_from_tuple
获取此示例:
namespace detail { template <class T, class Tuple, std::size_t... I> constexpr T make_from_tuple_impl( Tuple&& t, std::index_sequence<I...> ) { return T(std::get<I>(std::forward<Tuple>(t))...); } } // namespace detail template <class T, class Tuple> constexpr T make_from_tuple( Tuple&& t ) { return detail::make_from_tuple_impl<T>(std::forward<Tuple>(t), std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{}); }
并替换std::tuple_size_v<...>
为std::tuple_size<...>::value
.
这是针对T(...)
版本的。您需要替换T(...)
为T{...}
以获取T{...}
我在上面实现的版本。
推荐阅读
- javascript - 如何执行数组
在平行下 - php - prepare() 函数的问题:语法错误或访问冲突:1064 您的 SQL 语法有错误
- django - 令牌身份验证在 localhost 中工作正常,但在 ubuntu 服务器上不起作用(Djangorestframework)
- vb.net - MS ACCES 中的数据输入未更新
- c++ - D2D 坐标与屏幕坐标不匹配
- html - 全屏大小的 div 的 CSS 技巧将我的列表项向右推
- html - 如何在悬停和单击时切换 HTML/CSS 动画
- google-apps-script - Googlesheet 脚本复制范围,但在源数据加载时不复制
- scheme - 在Scheme中定义一个返回表达式运算符的宏?
- twitter-bootstrap-3 - 网格行为 Bootstrap4 与 Bootstrap3