[英]C++17 decorate lambda or member function with non-capturing lambda
我正在尝试制作一个 function,它返回一个非捕获 lambda(因此它可以转换为一个 function 指针)装饰一个内部 function,其中内部 function 可以是 8835508.86348 指针或 84a71988 指针
Compiler Explorer 链接供参考,我将在下面对其进行剖析。
我提出了两种策略,一种用于 lambda,另一种用于成员函数。 具体来说,对于 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)...);
};
}
将 lambda 保存为static
允许在非捕获 lambda 中使用callable
。这很好,因为decorate_lambda
模板实例化对于每个 lambda (IIRC) 都是唯一的。
对于成员函数,策略有些不同(注意模板参数)
template <auto callable>
auto decorate_memfn() {
return [](auto... args) {
return 100 + std::mem_fn(callable)(std::forward<decltype(args)>(args)...);
};
}
然后我可以做类似的事情
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;
导致 function 指针可用于例如 C 接口(最终)。
我想要的最终结果是将decorate_lambda
和decorate_memfn
滚动到单个decorate(lambda_or_memfn)
function (使用模板专业化, if constexpr
,或其他)。 例如
decorate([](int i) { return i + 1; });
decorate(&Worker::work);
即基本上我想要decorate_memfn(&Worker::work)
而不是decorate_memfn<&Worker::work>()
。 问题是
decorate_memfn
中的静态/全局变量。 有没有办法强制编译器识别参数来自静态/全局参数,从而允许它在 lambda 中使用而不捕获?static
技巧做一些类似于decorate_lambda
的事情对成员 function 指针不起作用,因为模板实例化不一定是唯一的(即如果两个Callable
具有相同的签名)。 不过,也许有办法让它变得独一无二?我知道 C++20 可以提供帮助,但不幸的是我被 C++17 困住了。
非常感谢任何提示!
首先,你的decorate_lambda
有问题:如果你用有状态的可调用函数调用它,它会无声地中断。 作为一个简单的检查,您可以仅在std::is_empty_v
为真时才允许调用。
我想要的最终结果是将 decorate_lambda 和 decorate_memfn 合并为一个 decorate(lambda_or_memfn) function
您可以使用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.