作为函数的参数-6ren"> 作为函数的参数-这是一个非常好的(不是我的)示例,您可以如何扩展(或“分解”)元组作为函数的参数: template struct index_tuple_type { template using append-6ren">
gpt4 book ai didi

c++ - "unpack"std::array 作为函数的参数

转载 作者:太空狗 更新时间:2023-10-29 20:03:31 24 4
gpt4 key购买 nike

这是一个非常好的(不是我的)示例,您可以如何扩展(或“分解”)元组作为函数的参数:

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);
}

Live version

我在想你怎么能用 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 来做到这一点?那么返回的类型可以扣除吗?

我也想知道,有工具来“解压”tuplearray是否可以递归地“解压”(可能使用 enable_if )结构,如 tuple<array<int, 2>, tuple<array<double,3>, ...等等?某种树 tuplearray是 Twig ,其他种类是树叶?

最佳答案

// enable argument dependent lookup on `get` call:
namespace aux {
using std::get;
template<size_t N, class T>
auto adl_get( T&& )->decltype( get<N>(std::declval<T>()) );
}
using aux::adl_get;
template<class F, class TupleLike, size_t...Is>
auto explode( F&& f, TupleLike&& tup, std::index_sequence<Is...> )
-> std::result_of_t< F( decltype(adl_get<Is>(std::forward<TupleLike>(tup)))... ) >
{
using std::get; // ADL support
return std::forward<F>(f)( get<Is>(std::forward<TupleLike>(tup))... );
}

是第一步。 std::index_sequence是C++14,但在C++11中很容易实现。

接下来的步骤也很简单。

首先,一个 traits 类,它规定了哪些类型类似于元组。我会继续,只是鸭式使用它们,但是我们将要使用的许多函数和特征类对 SFINAE 不友好:

template<class T>
struct tuple_like:std::false_type{};
template<class... Ts>
struct tuple_like<std::tuple<Ts...>>:std::true_type{};
template<class... Ts>
struct tuple_like<std::pair<Ts...>>:std::true_type{};
template<class T, size_t N>
struct tuple_like<std::array<T,N>>:std::true_type{};

接下来,重载 explode仅适用于 tuple_like类型:

template<class F, class TupleLike,
class TupleType=std::decay_t<TupleLike>, // helper type
class=std::enable_if_t<tuple_like<TupleType>{}>> // SFINAE tuple_like test
auto explode( F&& f, TupleLike&& tup )
-> decltype(
explode(
std::declval<F>(),
std::declval<TupleLike>(),
std::make_index_sequence<std::tuple_size<TupleType>{}>{}
)
)
{
using indexes = std::make_index_sequence<std::tuple_size<TupleType>{}>;
return explode(
std::forward<F>(f),
std::forward<TupleLike>(tup),
indexes{}
);
}

如果缺少constexpr支持你需要改变一些{}::value .

上面的技巧适用于对、数组或元组。如果你想添加对其他类似元组类型的支持,只需将特化添加到 tuple_like并确保 std::tuple_size适合您的类型和get<N>是 ADL 重载的(在类型的封闭命名空间中)。


std::make_index_sequence也是 C++14,但很容易用 C++11 编写。

template<size_t...>
struct index_sequence{};
namespace details {
template<size_t count, size_t...Is>
struct mis_helper:mis_helper<count-1, count-1, Is...> {};
template<size_t...Is>
struct mis_helper<0,Is...> {
using type=index_sequence<Is...>;
};
}
template<size_t count>
using make_index_sequence=typename details::mis_helper<count>::type;

(对于 C++14 库来说,QOI 很差,它应该至少使用对数下降,因为它需要 O(n) 模板递归模板实例化来获取大小为 n 的列表。但是,n 是否小于 a几百个,没关系)。

std::enable_if_t<?>是 C++14,但在 C++11 中只是 typename std::enable_if<?>::type .

关于c++ - "unpack"std::array<T,N> 作为函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28440210/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com