C++ 迭代器缩减器模式,用于可能返回值也可能不返回值的函数

C++ 迭代器缩减器模式,用于可能返回值也可能不返回值的函数,c++,c++11,C++,C++11,以下函数对每个元素应用一个函子并减少返回值: template <class FCT, class RED> RED::TYPE forAllElements(FCT functor, RED reducer){ for(/* all elem in elements */){ reducer(functor(elem)); } return reducer.value; } 但这不会编译,因为我有reducer(functor(elem)),其中void函数的

以下函数对每个元素应用一个函子并减少返回值:

template <class FCT, class RED>
RED::TYPE forAllElements(FCT functor, RED reducer){
  for(/* all elem in elements */){
    reducer(functor(elem));
  }
  return reducer.value;
}
但这不会编译,因为我有
reducer(functor(elem))
,其中void函数的不存在的返回值作为参数

有没有一种方法可以使它在不复制
void
和非
void
情况下的元素的情况下对void函子起作用?


(对于怀疑XY问题的人:我基本上知道迭代和减少的不同方法,我认为提出的回调方法适合我的情况。我只是想知道如何避免“返回值+减少”和“仅回调”情况下出现重复代码。)

我认为您可以创建一个
VoidReducer
类,而不是
返回reducer.value
您需要
返回reducer.getvalue()。然后,只需使
void VoidReducer::getvalue(){}

我还没有测试过这一点,但这个想法应该是可行的。允许您
返回f()
如果
f
和当前函数都有返回类型
void

编辑
现在我更仔细地阅读了这个问题,我发现您要问的问题是行
reducer(functor(elem))
为此,我将基于
decltype(functor(elem))
编译时分派

模板
无效组合(函子函子、减缩器和减缩器、Elem Elem、std::true\u类型)
{
函子(elem);
}
模板
无效组合(函子函子、减缩器和减缩器、Elem Elem、std::false\u类型)
{
还原子(函子(elem));
}
模板
无效组合(函子函子、减缩器和减缩器、元素元素)
{
组合(函子、减缩器、元素、std::is_same());
}
然后调用
Combine
而不是
reducer(functor(elem))
将正确地减少
functor
的返回值,如果且仅当它不是无效的


PS:撒上引用和
std::forward
调用来品尝味道。

如果您仍然想使用
for allelements
函数,那么如果直接使用
std::for_each
,您可以创建一个不带减缩器的函数重载,只需在内部使用
std::for_each

template <class FCT>
void forAllElements(FCT functor){
    std::for_each(std::begin(...), std::end(...), functor);
}

...

forAllElements(FunctorThatReturnsNothing());
模板
元素的void(FCT函子){
std::for_each(std::begin(…),std::end(…),functor);
}
...
对于allelement(functorhatturnsnoothing());

如果无法为容器获取“迭代器”(如果使用非标准容器或指针),您当然可以拥有自己的循环,只需调用
functor

一种干净灵活的方法是返回函数对象本身,而不是硬编码的
字段

template <class FCT, class RED>
RED forAllElements(FCT functor, RED reducer){
  for(/* all elem in elements */){
    reducer(functor(elem));
  }
  return reducer;
}
模板
元素的红色(FCT函子,红色还原子){
对于(/*元素中的所有元素*/){
还原子(函子(elem));
}
回流减速机;
}
然后,该操作可以没有返回值,甚至可以有多个返回值,并带有信息性名称

您的原始方法可以看作是此基本组件上的方便包装器:

template <class FCT, class RED>
RED::TYPE forAllElements_convenience(FCT functor, RED reducer){
  return forAllElements(functor, reducer).value;
}
模板
红色::类型为Allelements\u便利(FCT函子,红色减缩器){
返回元素(函子、减缩器).value;
}

那么基本上你想要什么?@JoachimPileborg,请参见问题的最后一部分,括号内。我知道我可以使用迭代器实现这一点,但在当前情况下,所提供的回调解决方案是有利的。最干净的方法是
返回reducer
,而不是
返回reducer.value
。你能重构你的代码来使用它吗?@filipos:这真是个好主意。我得检查一下这是否可能。
template <class FCT, class RED>
RED forAllElements(FCT functor, RED reducer){
  for(/* all elem in elements */){
    reducer(functor(elem));
  }
  return reducer;
}
template <class FCT, class RED>
RED::TYPE forAllElements_convenience(FCT functor, RED reducer){
  return forAllElements(functor, reducer).value;
}