这里有一个非常好的例子(不是我的),展示了如何将元组作为参数传递到函数中:
template<int ...I> struct index_tuple_type {
template<int N> using append = index_tuple_type<I..., N>;
};
template<int N> struct make_index_impl {
using type = typename make_index_impl<N-1>::type::template append<N-1>;
};
template<> struct make_index_impl<0> { using type = index_tuple_type<>; };
template<int N> using index_tuple = typename make_index_impl<N>::type;
template <typename I, typename ...Args>
struct func_traits;
template <typename R, int ...I, typename ...Args>
struct func_traits<R, index_tuple_type<I...>, Args...> {
template <typename TT, typename FT>
static inline R call(TT &&t, FT &&f) {
return f(std::get<I>(std::forward<TT>(t))...);
}
};
template<
typename FT,
typename ...Args,
typename R = typename std::result_of<FT(Args&&...)>::type
>
inline R explode(std::tuple<Args...>& t, FT &&f) {
return func_traits<R, index_tuple<sizeof...(Args)>, Args...>
::call(t, std::forward<FT>(f));
}
然后你可以这样使用它:
void test1(int i, char c) {
printf("%d %c\n", i, c);
}
int main() {
std::tuple<int, char> t1{57, 'a'};
explode(t1, test1);
}
我在想,如何使用std::array
完成类似的操作,因为它与元组很相似。std::get<N>
可用于std::array
,所以我认为很容易修改此解决方案。但是像这样的代码并不起作用:
template<
typename FT,
typename Arg,
std::size_t I,
typename R = typename std::result_of<FT(Arg&&)>::type
>
inline R explode(std::array<Arg, I>& t, FT &&f) {
return func_traits<R, index_tuple<I>, Arg>::
call(t, std::forward<FT>(f));
}
void test2(int i1, int i2) {
printf("%d %d\n", i1, i2);
}
int main() {
std::array<int, int> t1{1, 2};
explode(t2, test1);
}
因为部分
std::result_of<FT(Arg&&)>::type
,参数类型Arg&&
是错误的,并且result_of
没有字段type
。对于元组Args&&...
已经扩展,但现在应该“重复”I
次。是否有一种使用result_of
来完成这个过程,以便可以推断返回类型的方法?另外,我想知道,如果有“解包”
tuple
和array
的工具,是否有可能递归“解包”像tuple<array<int, 2>, tuple<array<double,3>, ...
这样的结构,等等?一种类似树形的结构,其中tuple
和array
是分支,其他类型则是叶子?
std::forward
中的左值引用硬编码为类型模板参数等同于“无操作”,你可能想把t
作为它的参数。另外,使用尾返回类型。 - Piotr Skotnickistd::forward<std::tuple<Args...>>(t)
等同于std::move(t)
(无条件)。 - Piotr Skotnickistd::tuple
一样与std::array
一起使用。在此处查看实例。 - DanielKO