如何使用折叠表达式实现“多米诺骨牌”或“级联”更新功能?

问题描述 投票:0回答:2

我正在编写一个可变参数模板函数,它应该实现“多米诺骨牌”更新。也就是说:给定一个谓词

p
,它应该迭代多个
lval
(通过引用传递)并将
val
分配给它们,直到
p(val, lval)
返回
false
,此时进程停止。

这是我当前的实现:

#include <iostream>
#include <functional>

template<class Val, class P>
void domino_update(P, Val&) {}

template<class Val, class Lval, class... More, class P>
void domino_update(P p, Val&& val, Lval& lval, More&... more)
{
    if (p(val, lval)) {
        lval = val; // No need to forward since it'd potentially chain more copies anyway
        domino_update(p, val, more...);
    }
}

int main(int, char**)
{
    int i = 8, j = 9, k = 1;
    domino_update(std::less{}, 2, i, j, k);
    std::cout << i << ' ' << j << ' ' << k << '\n'; // Prints 2 2 1
    return 0;
}

但是,我不喜欢它是递归的。

我可以使用fold表达式来避免使用递归(并避免需要为模板实现基本情况),同时保持短路逻辑(即,

p
一旦返回就不应再次调用)
false
)?怎么办?

c++ c++17 variadic-templates
2个回答
2
投票

这是一种方法:

template <class P, class Val, class... Lvals>
void domino_update(P p, Val&& val, Lvals&&... lval) {
    ((/*if*/        p(val, lval)
      /*then*/      && (lval = val, true))
      /*and next*/  && ...);
}

演示


1
投票

接受挑战。

template<typename P, typename Val, typename... Lval>
void dominoe_update(P p, Val&& val, Lval&... lval)
{
    bool go = true;
    ( (go && (go = p(val, lval)) ? (void(lval = val), 0) : 0), ...);
}

演示

© www.soinside.com 2019 - 2024. All rights reserved.