分发参数包以调用两个函子
Distribute argument parameter pack to invoke two functors
我试图通过一个给定的参数包(typename Args... args
)调用两个函数对象,提供了一个整数参数来标记我需要拆分包以正确调用两个功能对象的边界。
考虑以下示例:
Args... = <int, int, std::vector<int>, std::vector<int>>
unsigned Bounds = 2;
functor Foo (left) and Bar (right)
// Foo is invoked with <int, int>
// Bar is invoked with <std::vector<int>, std::vector<int>>
// An evaluator template class is invoked to merge the result of both,
// for example with an add (operator+) operation
我的想法是创建两个整数序列,并使用std::get
用这两个整数顺序同时调用两个函数对象:
// Sequence creator
template<unsigned Position, unsigned Count, unsigned... Pack>
struct make_sequence
: std::conditional<
Count == 0,
std::common_type<sequence<Pack...>>,
make_sequence<Position + 1, Count - 1, Pack..., Position>
>::type { };
// Create a sequence from inclusive from to exclusive to
template<unsigned InclusiveFrom, unsigned ExclusiveTo>
using make_sequence_from_to_t = typename make_sequence<
InclusiveFrom,
(ExclusiveTo <= InclusiveFrom) ? 0U : (ExclusiveTo - InclusiveFrom)
>::type;
template<typename LeftType, typename RightType, unsigned Bounds, typename Evaluator>
class distribute_functor
{
LeftType left_;
RightType right_;
template<unsigned... LeftSeq, unsigned... RightSeq, typename... Args>
auto internal_invoke(sequence<LeftSeq...>, sequence<RightSeq...>, Args... args)
{
return Evaluator::evaluate(left_(std::get<LeftSeq>(args)...),
// ~~~~~~~~~~~~~~~^^^^^^^~~^^^^~~~~~
// error C3528: 'LeftSeq': the number of
// elements in this pack expansion does not
// match the number of elements in 'args'
right_(std::get<RightSeq>(args)...));
}
public:
template<typename Left, typename Right>
distribute_functor(Left left, Right right)
: left_(std::forward<Left>(left)), right_(std::forward<Right>(right)) { }
template<typename... Args>
auto operator() (Args... args)
{
return internal_invoke(make_sequence_from_to_t<0, Bounds>{},
make_sequence_from_to_t<Bounds, sizeof...(Args)>{},
std::forward<Args>(args)...);
}
};
但是,VisualStudio14编译器抱怨arguments包和序列中的参数计数不匹配:
错误C3528:"LeftSeq":此包扩展中的元素数与"args"中的元素数目不匹配
仍然有一种方法可以使用std::tuple
进行函子调用,我不喜欢这种方法
是否有其他或更好的方法可以在一个参数包的一步中部分调用两个函数对象
std::get
不能以这种方式使用。
你应该这样写internal_invoke
:
template<unsigned... LeftSeq, unsigned... RightSeq, typename ArgsAsTuple>
auto internal_invoke(sequence<LeftSeq...>, sequence<RightSeq...>,ArgsAsTuple&& args) const
{
return Evaluator::evaluate(left_(std::get<LeftSeq>(args)...),
right_(std::get<RightSeq>(args)...));
}
并用forward_as_tuple
:调用它
return internal_invoke(make_sequence_from_to_t<0, Bounds>{},
make_sequence_from_to_t<Bounds, sizeof...(Args)>{},
std::forward_as_tuple(args...));
解释:
必须分别展开两个不同浓度的参数包。当您编写std::get<LeftSeq>(args)...
时,您尝试将不同arity的包展开在一起。这是不可能的。你应该写std::get<LeftSeq>(args... /* 1st expand/) ... /* 2nd expand */
。这在语法上是正确的,但与std::get
API不匹配。std::forward_as_tuple可以帮助您,并且是专门为这些类型的用例编写的。
编辑:
如果您想避免使用元组,那么您必须编写自己版本的std::get
以满足您的需要,前提是您可以像上面解释的那样正确地扩展参数。
相关文章:
- 为什么模板参数推导不适用于仅指定前两个参数的可变参数模板类?
- C++如何在 switch 语句中放置两个参数
- 为什么我不能用两个参数重载 C++ 运算符 []?
- C++添加检查以避免读取两个参数
- 宏的定义从一个值创建两个参数
- C++ 如何使用一个参数从派生类构造函数中调用具有两个参数的超类构造函数
- 通过将两个参数包的元素线程化为类型对来解压缩这两个参数包
- 'int main(int, int, std::__cxx11::string, std::__cxx11::string)'只需要零或两个参数 [-Wmain]
- 错误:函数调用中有两个参数
- Qt 线程两个参数
- 为什么lambda函数用于stl函数,例如sort(),c 中的max_element()函数以两个参数为输入
- 警告:用两个参数构造函数返回对象时,表达结果未使用
- 具有两个参数的 Decltype 修改类型
- 将两个参数传递到谓词remove_if
- 同时扩展两个参数包
- 用两个参数调用新操作员,但没有分配
- 在Variadic模板中交换两个参数
- C CPPUNIT_ASSERT具有两个参数
- 具有两个参数的乘法函数
- 使用一个可选参数获取两个参数到main