"unpack" std::array<T,N> 作为函数的参数
"unpack" std::array<T,N> as arguments to function
这里有一个很好的例子(不是我的),你可以将元组展开(或"爆炸")作为函数的参数:
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 %cn", 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 %dn", i1, i2);
}
int main() {
std::array<int, int> t1{1, 2};
explode(t2, test1);
}
由于部分CCD_ 4。参数类型Arg&&
错误,并且result_of
没有字段type
。对于元组Args&&...
进行了扩展,但现在应该"重复"I
次。有没有一种方法可以使用result_of
来实现这一点,以便可以扣除返回的类型?
我还想知道,有了"解包"tuple
和array
的工具,是否有可能像tuple<array<int, 2>, tuple<array<double,3>, ...
等递归地"解包(可能使用enable_if
)"结构?tuple
和array
是树枝,其他类型是叶子的某种树?
// 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{};
接下来,一个仅适用于tuple_like
类型的explode
过载:
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重载的(在类型的封闭命名空间中)。
CCD_ 26也是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,它应该至少使用日志下降,因为它需要大小为n的列表的O(n)模板递归模板实例化。然而,如果n小于几百,这无关紧要)。
std::enable_if_t<?>
是C++14,而在C++11中只是typename std::enable_if<?>::type
。
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数