【发布时间】:2015-02-10 19:29:28
【问题描述】:
这是一个很好的(不是我的)例子,你可以如何扩展(或“分解”)元组作为函数的参数:
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 的工具是否可以递归地“解包”(可能使用enable_if)结构,如tuple<array<int, 2>, tuple<array<double,3>, ... 等等?某种树,其中tuple 和array 是树枝,而其他类型是树叶?
【问题讨论】:
-
std::forward将左值引用编码为类型模板参数等于“无操作”。你可能打算把t作为它的论点。顺便说一句,请改用trailing return type like here -
您是否考虑过创建一个将数组转换为引用元组的函数?
-
@PiotrS。更正了
forward,我的错误扩展宏以错误的方式进行。 @Hurkyl 是的,我想过,但这不是一点点。 -
@The_Ham 它仍然不会像你想象的那样工作。现在
std::forward<std::tuple<Args...>>(t)等于std::move(t)(无条件) -
在我看来,将一堆
tuple-likes 扁平化为一个tuple是一个独特的问题。我回答了你的第一个问题。
标签: c++ templates c++11 stdarray stdtuple