gpt4 book ai didi

c++ - 在编译时迭代过滤与谓词匹配的参数

转载 作者:可可西里 更新时间:2023-11-01 17:49:16 25 4
gpt4 key购买 nike

上下文

首先,一些上下文:我正在使用一个空的 struct称为 nothing模拟类似于 "regular void " 的东西为了美化一些依赖于将多个函数对象链接在一起的接口(interface)。

struct nothing { };

示例用法:

when_all([]{ return 0; }, []{ }, []{ return 'a'; })
.then([](int, char){ }); // result of lambda in the middle ignored

在上面的例子中,实际发生的是我打包了传递给 when_all 的函数对象的所有结果。在std::tuple , 转换 voidnothing (在此示例中:std::tuple<int, nothing, char> ),然后我使用一个名为 apply_ignoring_nothing 的辅助函数通过解包 std::tuple 调用函数对象, 忽略 nothing 的元素.

auto f_then = [](int, char){ };
auto args = std::tuple{0, nothing{}, 'a'};
apply_ignoring_nothing(f_then, args); // compiles

apply_ignoring_nothing根据 call_ignoring_nothing 实现.


问题

我有一个函数 call_ignoring_nothing具有以下签名:

template <typename F, typename... Ts>
constexpr decltype(auto) call_ignoring_nothing(F&& f, Ts&&... xs);

此函数将调用 f通过完美转发所有xs...编译时 is_nothing_v<T>返回 false .

is_nothing_v定义如下:

template <typename T>
inline constexpr bool is_nothing_v = std::is_same_v<std::decay_t<T>, nothing>;

我实现的方式 call_ignoring_nothing递归。基本情况只需要 f并简单地调用它:

#define FWD(x) ::std::forward<decltype(x)>(x)

template <typename F>
constexpr decltype(auto) call_ignoring_nothing(F&& f)
{
return returning_nothing_instead_of_void(FWD(f));
}

递归情况采用f , x , 和 xs... , 并有条件地绑定(bind) x作为f之一的参数如果 !is_nothing_v<decltype(f)>通过 lambda。然后它递归 call_ignoring_nothing将新创建的 lambda 作为 f 传递:

template <typename F, typename T, typename... Ts>
constexpr decltype(auto) call_ignoring_nothing(F&& f, T&& x, Ts&&... xs)
{
return call_ignoring_nothing(
[&](auto&&... ys) -> decltype(auto) {
if constexpr(is_nothing_v<T>)
{
return FWD(f)(FWD(ys)...);
}
else
{
return FWD(f)(FWD(x), FWD(ys)...);
}
},
FWD(xs)...);
}

我想实现 call_ignoring_nothing以迭代的方式,可能利用 pack expansion 在没有递归的情况下过滤掉参数。

是否可以实现 call_ignoring_nothing没有递归?我想不出任何允许在包扩展期间过滤掉参数的技术。

最佳答案

与 Griwes 的建议没有太大区别,但是......我想你可以使用 std::apply()std::tuple_cat() std::get() 和为空或根据 is_nothing_v 的值具有值的元组。

我的意思是……类似 [编辑:根据 T.C. 的建议进行了改进。以及来自 OP 本身的示例(Vittorio Romeo)]

template <bool B, typename ... Ts>
constexpr auto pick_if (Ts && ... xs)
{
if constexpr ( B )
return std::forward_as_tuple(std::forward<Ts>(xs)...);
else
return std::tuple{};
}

template <typename F, typename ... Ts>
constexpr decltype(auto) call_ignoring_nothing (F && f, Ts && ... xs)
{
return std::apply(f,
std::tuple_cat(pick_if<!is_nothing_v<Ts>>(std::forward<Ts>(xs))...)
);
}

下面是一个工作示例

#include <tuple>
#include <iostream>
#include <type_traits>

struct nothing { };

template <typename T>
constexpr bool is_nothing_v = std::is_same<std::decay_t<T>, nothing>::value;

template <bool B, typename ... Ts>
constexpr auto pick_if (Ts && ... xs)
{
if constexpr ( B )
return std::forward_as_tuple(std::forward<Ts>(xs)...);
else
return std::tuple{};
}

template <typename F, typename ... Ts>
constexpr decltype(auto) call_ignoring_nothing (F && f, Ts && ... xs)
{
return std::apply(f,
std::tuple_cat(pick_if<!is_nothing_v<Ts>>(std::forward<Ts>(xs))...)
);
}

float foo (int a, float b) { return a + b; }

int main ()
{
std::cout << call_ignoring_nothing(foo, nothing{}, 12, nothing{},
2.3f, nothing{}); // print 14.3
}

live example on wandbox

关于c++ - 在编译时迭代过滤与谓词匹配的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46266795/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com