区分两个包扩展
Differentiate between two pack expansions
有没有办法明确指定哪个 ...
指的是哪个扩展包?在我的代码中,我有两个我想在不同级别应用的包扩展:
template<typename T, int N>
struct MyArr
{
T e[N];
constexpr T& operator[](int i) { return e[i]; }
constexpr const T& operator[](int i) const { return e[i]; }
MyArr() : e{} {}
template<typename ...type_pack>
MyArr(const type_pack&... pack) : e{pack...}
{
static_assert(sizeof...(pack)==N,
"Argument count must match the size.");
}
};
template<typename type_lhs, typename type_rhs>
auto add(const type_lhs& lhs, const type_rhs& rhs)
{
return lhs + rhs;
}
template<int ...I, typename type_head, typename ...type_pack, int N, typename Function>
auto apply(Function&& op,
const MyArr<type_head,N>& head, const MyArr<type_pack,N>&... pack)
{
return MyArr<type_head,N>((op(head[I],(pack[I])...))...);
// expand pack[I]- ^ , ^ - expand I...
};
int main()
{
MyArr<int,3> a(1,2,3);
return apply<0,1,2>(add<int,int>, a, a);
}
本质上,我想得到:
(op(head[0], get<0>(pack)[0], ..., get<M-1>(pack)[0]),
...,
op(head[N-1], get<0>(pack)[N-1], ..., get<M-1>(pack)[N-1]))
感谢 OznOg 的建议,我通过在中间创建一个函数让它工作:
template<int ...I, typename type_head, typename ...type_pack, int N, typename Function>
auto apply(Function&& op,
const MyArr<type_head,N>& head, const MyArr<type_pack,N>&... pack)
{
auto op2 = [&](int i) { return op(head[i], pack[i]...);};
return MyArr<type_head,N>(op2(I)...);
};
在这种特殊情况下,我看到的唯一方法是使用辅助函数(getVal()
,在以下示例中)
template <int I, typename type_head, typename ...type_pack, int N,
typename Function>
auto getVal (Function&& op, MyArr<type_head,N> const & head,
MyArr<type_pack,N> const & ... pack)
{ return op(head[I], pack[I]...); }
template <int ... Is, typename type_head, typename ...type_pack, int N,
typename Function>
auto apply (Function && op, MyArr<type_head,N> const & head,
MyArr<type_pack,N> const &... pack)
{ return MyArr<type_head,N>{ getVal<Is>(op, head, pack...)... }; }
问题是你有
(pack[I])...
所以(据我所知)没有办法说扩展适用于 pack
而不是 I
.
有中间函数
//.......................VVV expand pack
getVal<Is>(op, head, pack...)...
//...........................^^^ expand Is
您可以使用括号来分隔级别。
但是你必须把pack
和Is
分开。
有没有办法明确指定哪个 ...
指的是哪个扩展包?在我的代码中,我有两个我想在不同级别应用的包扩展:
template<typename T, int N>
struct MyArr
{
T e[N];
constexpr T& operator[](int i) { return e[i]; }
constexpr const T& operator[](int i) const { return e[i]; }
MyArr() : e{} {}
template<typename ...type_pack>
MyArr(const type_pack&... pack) : e{pack...}
{
static_assert(sizeof...(pack)==N,
"Argument count must match the size.");
}
};
template<typename type_lhs, typename type_rhs>
auto add(const type_lhs& lhs, const type_rhs& rhs)
{
return lhs + rhs;
}
template<int ...I, typename type_head, typename ...type_pack, int N, typename Function>
auto apply(Function&& op,
const MyArr<type_head,N>& head, const MyArr<type_pack,N>&... pack)
{
return MyArr<type_head,N>((op(head[I],(pack[I])...))...);
// expand pack[I]- ^ , ^ - expand I...
};
int main()
{
MyArr<int,3> a(1,2,3);
return apply<0,1,2>(add<int,int>, a, a);
}
本质上,我想得到:
(op(head[0], get<0>(pack)[0], ..., get<M-1>(pack)[0]),
...,
op(head[N-1], get<0>(pack)[N-1], ..., get<M-1>(pack)[N-1]))
感谢 OznOg 的建议,我通过在中间创建一个函数让它工作:
template<int ...I, typename type_head, typename ...type_pack, int N, typename Function>
auto apply(Function&& op,
const MyArr<type_head,N>& head, const MyArr<type_pack,N>&... pack)
{
auto op2 = [&](int i) { return op(head[i], pack[i]...);};
return MyArr<type_head,N>(op2(I)...);
};
在这种特殊情况下,我看到的唯一方法是使用辅助函数(getVal()
,在以下示例中)
template <int I, typename type_head, typename ...type_pack, int N,
typename Function>
auto getVal (Function&& op, MyArr<type_head,N> const & head,
MyArr<type_pack,N> const & ... pack)
{ return op(head[I], pack[I]...); }
template <int ... Is, typename type_head, typename ...type_pack, int N,
typename Function>
auto apply (Function && op, MyArr<type_head,N> const & head,
MyArr<type_pack,N> const &... pack)
{ return MyArr<type_head,N>{ getVal<Is>(op, head, pack...)... }; }
问题是你有
(pack[I])...
所以(据我所知)没有办法说扩展适用于 pack
而不是 I
.
有中间函数
//.......................VVV expand pack
getVal<Is>(op, head, pack...)...
//...........................^^^ expand Is
您可以使用括号来分隔级别。
但是你必须把pack
和Is
分开。