繁体   English   中英

C++17 装饰 lambda 或成员 function 非捕获 lambda

[英]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_lambdadecorate_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>() 问题是

  • 将成员 function 指针作为参数而不是模板参数传递,意味着成员 function 指针不再被视为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM