请考虑以下代码:
static constexpr size_t Num {2};
struct S {
std::array<size_t, Num> get () { return {1, 2}; }
};
struct S1 : S {};
struct S2 : S {};
struct M {
template <typename T>
typename std::enable_if<std::is_same<T, S1>::value, S1>::type get () const {
return S1 {};
}
template <typename T>
typename std::enable_if<std::is_same<T, S2>::value, S2>::type get () const {
return S2 {};
}
};
Run Code Online (Sandbox Code Playgroud)
我想要一个合并两个或多个std::arrays 的功能std::array.
到目前为止,我结束了这样的事情:
template <typename Mode, typename... Rs, size_t... Ns>
std::array<size_t, sizeof... (Rs)*Num> get_array (const Mode& mode, Sequence::Sequence<Ns...>) {
return {std::get<Ns> (mode.template get<Rs...> ().get ())...};
}
Run Code Online (Sandbox Code Playgroud)
我希望得到以下代码
M m;
auto x = get_array<M, S1, S2> (m, Sequence::Make<2> {});
Run Code Online (Sandbox Code Playgroud)
生产std::array<size_t, 4>充满{1, 2, 1, 2}.
在哪里Sequence::Sequence和Sequence::Make在这里描述.
我知道,放置...的Rs在这方面是不正确的(如果sizeof... (Rs)是1,那么它是好的,std::array<size_t, 2>有{1, 2}返回),但我不知道在哪里把它做扩展,看起来像这样:
std::get<0> (mode.template get<Rs[0]> ().get ()),
std::get<1> (mode.template get<Rs[0]> ().get ()),
std::get<0> (mode.template get<Rs[1]> ().get ()),
std::get<1> (mode.template get<Rs[1]> ().get ());
Run Code Online (Sandbox Code Playgroud)
当然Rs[0]我的意思是参数包中的第一个类型.
它甚至可能吗?
首先,这基本上是要求连接任意数量的数组。这与连接任意数量的元组非常相似,即使在 C++11 中,也有一个标准库函数:std::tuple_cat()。这让我们差不多到了:
template <class... Ts, class M>
auto get_array(M m) -> decltype(std::tuple_cat(m.template get<Ts>()...)) {
return std::tuple_cat(m.template get<Ts>()...);
}
Run Code Online (Sandbox Code Playgroud)
请注意,我翻转了模板参数,因此这只是get_array<T1, T2>(m)不必编写get_array<M, T1, T2>(m).
现在的问题是,我们该怎么写呢array_cat?我们只需使用tuple_cat结果并将tuple其转换为array. 假设 的实现index_sequence可用(无论如何,这都是您想要的):
template <class T, class... Ts, size_t... Is>
std::array<T, sizeof...(Ts)+1> to_array_impl(std::tuple<T, Ts...>&& tup,
std::index_sequence<Is...> ) {
return {{std::get<Is>(std::move(tup))...}};
}
template <class T, class... Ts>
std::array<T, sizeof...(Ts)+1> to_array(std::tuple<T, Ts...>&& tup) {
return to_array_impl(std::move(tup), std::index_sequence_for<T, Ts...>());
}
template <class... Tuples>
auto array_cat(Tuples&&... tuples) -> decltype(to_array(std::tuple_cat(std::forward<Tuples>(tuples)...))) {
return to_array(std::tuple_cat(std::forward<Tuples>(tuples)...));
}
Run Code Online (Sandbox Code Playgroud)
这给了你:
template <class... Ts, class M>
auto get_array(M m) -> decltype(array_cat(m.template get<Ts>()...)) {
return array_cat(m.template get<Ts>()...);
}
Run Code Online (Sandbox Code Playgroud)
它处理任意多种类型。