[英]C++17 decorate lambda or member function with non-capturing lambda
I'm trying to craft a function that returns a non-capturing lambda (so it can be converted to a function pointer) that decorates an inner function, where the inner function can be either a lambda or a member function pointer.我正在尝试制作一个 function,它返回一个非捕获 lambda(因此它可以转换为一个 function 指针)装饰一个内部 function,其中内部 function 可以是 8835508.86348 指针或 84a71988 指针
Compiler Explorer link for reference, which I'll dissect in the following. Compiler Explorer 链接供参考,我将在下面对其进行剖析。
I've come up with two strategies, one for lambdas and the other for member functions.我提出了两种策略,一种用于 lambda,另一种用于成员函数。 Specifically, for lambdas
具体来说,对于 lambda
template <typename Callable>
auto decorate_lambda(Callable&& lambda) {
static const Callable callable = std::forward<Callable>(lambda);
return [](auto... args) {
return 100 + callable(std::forward<decltype(args)>(args)...);
};
}
Saving off the lambda as a static
allows callable
to be used in a non-capturing lambda. This is fine because the decorate_lambda
template instantiation will be unique for each lambda (IIRC).将 lambda 保存为
static
允许在非捕获 lambda 中使用callable
。这很好,因为decorate_lambda
模板实例化对于每个 lambda (IIRC) 都是唯一的。
For member functions the strategy is somewhat different (note the template parameter)对于成员函数,策略有些不同(注意模板参数)
template <auto callable>
auto decorate_memfn() {
return [](auto... args) {
return 100 + std::mem_fn(callable)(std::forward<decltype(args)>(args)...);
};
}
I can then do something like然后我可以做类似的事情
const auto decorated_lambda =
decorate_lambda([](int i) { return i + 1; });
const auto decorated_memfn =
decorate_memfn<&Worker::work>();
int (*lambda_fnptr)(int) = decorated_lambda;
int (*memfn_fnptr)(Worker&, int) = decorated_memfn;
resulting in function pointers that can be used eg in a C interface (ultimately).导致 function 指针可用于例如 C 接口(最终)。
The end result that I would like is to roll decorate_lambda
and decorate_memfn
into a single decorate(lambda_or_memfn)
function (using template specialisation, if constexpr
, or whatever).我想要的最终结果是将
decorate_lambda
和decorate_memfn
滚动到单个decorate(lambda_or_memfn)
function (使用模板专业化, if constexpr
,或其他)。 Eg例如
decorate([](int i) { return i + 1; });
decorate(&Worker::work);
Ie essentially I would like to have decorate_memfn(&Worker::work)
rather than decorate_memfn<&Worker::work>()
.即基本上我想要
decorate_memfn(&Worker::work)
而不是decorate_memfn<&Worker::work>()
。 The problem is that问题是
decorate_memfn
.decorate_memfn
中的静态/全局变量。 Is there a way to force the compiler to recognize that a parameter is from a static/global and hence allow it's use within a lambda without capturing?decorate_lambda
with it's static
trick doesn't work for member function pointers because the template instantiation is not necessarily unique (ie if two Callable
s have the same signature).static
技巧做一些类似于decorate_lambda
的事情对成员 function 指针不起作用,因为模板实例化不一定是唯一的(即如果两个Callable
具有相同的签名)。 Maybe there is a way to make it unique, though? I understand C++20 could help, but unfortunately I'm stuck with C++17.我知道 C++20 可以提供帮助,但不幸的是我被 C++17 困住了。
Any hints much appreciated!非常感谢任何提示!
First, your decorate_lambda
is buggy: it silently breaks if you call it with a stateful callable.首先,你的
decorate_lambda
有问题:如果你用有状态的可调用函数调用它,它会无声地中断。 As a simple check, you could allow callables only if std::is_empty_v
is true.作为一个简单的检查,您可以仅在
std::is_empty_v
为真时才允许调用。
The end result that I would like is to roll decorate_lambda and decorate_memfn into a single decorate(lambda_or_memfn) function
我想要的最终结果是将 decorate_lambda 和 decorate_memfn 合并为一个 decorate(lambda_or_memfn) function
You can use std::integral_constant
您可以使用
std::integral_constant
template<auto x>
inline constexpr std::integral_constant<decltype(x), x> constant{};
template<typename T, typename F, F T::* x>
auto decorate(std::integral_constant<F T::*, x>)
{
return [](auto&&... args) {
return 100 + std::mem_fn(x)(decltype(args)(args)...);
};
}
auto d = decorate(constant<&Worker::work>);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.