可能返回值也可能不返回值的函数的迭代器缩减器模式
Iterator-reducer pattern for functions that may or may not return a value
以下函数对每个元素应用一个函子并减少返回值:
template <class FCT, class RED>
RED::TYPE forAllElements(FCT functor, RED reducer){
for(/* all elem in elements */){
reducer(functor(elem));
}
return reducer.value;
}
现在,有时我可能希望只对所有元素调用functor
,而不减少任何内容。基本上,我想有这样的东西:
class FunctorThatReturnsNothing{
void operator() (Elem e){
// do something, return nothing...
}
}
class DummyReducer{
using TYPE = void; // ??? something like that ???
template <class FCT>
void operator() (/* ??? what here */){
// do nothing...
}
}
forAllElements(FunctorThatReturnsNothing(), DummyReducer());
但这不会编译,因为我有reducer(functor(elem))
,其中void函数的不存在的返回值被当作参数。
有没有一种方法可以让它在不复制void
和非void
情况下的forAllElements的情况下适用于void函子
(对于怀疑XY问题的人:我基本上知道迭代和减少的不同方法,我认为所提出的回调方法适合我的情况。我只是想知道如何避免"返回值+减少"answers"只是回调"的情况出现重复代码。)
我认为您可以只创建一个VoidReducer
类,但您需要的不是return reducer.value;
,而是return reducer.getvalue();
。然后您只需制作void VoidReducer::getvalue(){}
。
我还没有对此进行测试,但这个想法应该可行。如果f
和当前函数都具有返回类型void
,则允许使用return f();
。
编辑
现在我更仔细地阅读了这个问题,我发现你问的问题是reducer(functor(elem));
行
为此,我将基于decltype(functor(elem))
编译时间调度。
template <class Functor, class Reducer, class Elem>
void Combine(Functor functor, Reducer & reducer, Elem elem, std::true_type)
{
functor(elem);
}
template <class Functor, class Reducer, class Elem>
void Combine(Functor functor, Reducer & reducer, Elem elem, std::false_type)
{
reducer(functor(elem));
}
template <class Functor, class Reducer, class Elem>
void Combine(Functor functor, Reducer & reducer, Elem elem)
{
Combine(functor, reducer, elem, std::is_same<decltype(functor(elem)), void>());
}
那么调用Combine
而不是reducer(functor(elem))
将正确地减少functor
的返回值,当且仅当它不是void时。
附言:撒上参考文献和std::forward
调用来品尝。
如果你仍然想使用forAllElements
函数,而直接使用std::for_each
,你可以创建一个不带减缩器的函数重载,只需在内部使用std::for_each
:
template <class FCT>
void forAllElements(FCT functor){
std::for_each(std::begin(...), std::end(...), functor);
}
...
forAllElements(FunctorThatReturnsNothing());
如果无法为容器获取"迭代器"(如果使用非标准容器或指针),当然可以有自己的循环,只需调用functor
。
一种干净而灵活的方法是返回函数对象本身,而不是硬编码的value
字段。
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;
}
- 从python中调用C++函数并获取返回值
- 为什么模板类中的对象不能返回值
- 返回值优化:显式移动还是隐式
- lock_guard是否保护返回值
- 调用CreateProcess()并获取字符串的返回值
- 如何使 windows 命令提示符在C++可执行文件上显示返回值?
- 编译器警告:执行到达值返回函数的末尾而不返回值
- 查找 GCD:并非所有控制路径都返回值
- 在 Arduino 上使用 sscanf 会导致与 const char * 不匹配,并且返回值始终相同,尽管输入值不同
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 如何从 std::thread 返回值
- 将返回值从 exe 传递到 bat,并将其传递给 C# 中的进程
- 方法错误"not all control paths return a value"和方法不返回值
- 如何读取 C++ SAFEARRAY**,该 SAFEARRAY** 是 COM 互操作的结果,其中 C# 返回值为
- 对fread的返回值感到困惑
- 程序不向函数返回值
- 如何在另一个线程中关闭 MFC 模式对话框并获取对话框返回值?
- 为什么将boost::move()的返回值分配给非常数引用在C++0x模式下失败,但在C++03模式下有效
- 可能返回值也可能不返回值的函数的迭代器缩减器模式
- 使用具有返回值的访客模式实现 AST 的最佳方法是什么?