Folly 提供了make_array 和make_array_with的帮助模板类了初始化std::array数组。
先来看make_array的实现:
template
constexpr array_detail::return_type
using value_type =
typename array_detail::return_type_helper
return {{static_cast
}
make_array的实现比较简单,首先声明一个value_type,它是通过return_type_helper对传入的实参进行类型推导来确定数组的元素类型。最后用{{…}}来将这些实参组合生成为intialize_list进行返回。
而return_type_helper利用std::common_type来确定传入的每个实参都可隐式转换的公共类型,看std::common_type的定义:
Determines the common type among all types T..., that is the type all T... can be implicitly converted to. If such a type exists (as determined according to the rules below), the member type names that type. Otherwise, there is no member type.
分析万make_array,那么再来分析make_array_with,它允许我们提供一个元素构造器(可调用对象,譬如仿函数,在c++17中可以是lambda函数)对array的元素在编译期进行设定。
以下主要分析一下make_array_with的实现过程:
先来看看make_array_with的定义
template
constexpr auto make_array_with(MakeItem const& make) {
return array_detail::make_array_with(make, make_index_sequence
}
在这个定义中,make_array_with需要输入一个元素构造器可调用对象,并用一个模板参数Size来设置将要生成的数组的元素个数, 这个版本的make_array_with又委托给了另外一个版本的make_array_with模板函数,如下:
template
FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN constexpr auto make_array_with(
MakeItem const& make,
index_sequence
return std::array
}
这个版本的make_array_with比较好理解,就是利用可变参数模板函数来生成一个用于array初始化的初始化列表,生成的数组的类型为make(0)的返回值对应的类型。
这里比较关键的是index_sequence
譬如,假设准备用make来生成类型为int包含4个元素的数组,那么展开后为:
make_array_with( MakeItem const& make,
index_sequence<0, 1, 2, 3 > ){
return std::array
}
那么这个index_sequence是怎么生成出来的呢?
这就要归功于make_index_sequence了,make_index_sequence根据其唯一的模板参数N来创建一个0到N-1的整数序列。
我们来看看std:: make_index_sequence的定义:
The class template std::integer_sequence represents a compile-time sequence of integers. When used as an argument to a function template, the parameter pack Ints can be deduced and used in pack expansion.
这样子,最终将make_array_with转化为对array的可变参数构造函数的调用。