C++17 用非捕获 lambda 修饰 lambda 或成员函数

C++17 decorate lambda or member function with non-capturing lambda

我正在尝试制作一个函数,该函数 returns 一个装饰内部函数的非捕获 lambda(因此它可以转换为函数指针),其中内部函数可以是 lambda或成员函数指针。

Compiler Explorer link供参考,后面会剖析

我提出了两种策略,一种用于 lambda,另一种用于成员函数。具体来说,对于 lambdas

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 允许 callable 用于非捕获 lambda。这很好,因为 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;

导致可以使用的函数指针,例如在 C 接口中(最终)。

我想要的最终结果是将 decorate_lambdadecorate_memfn 合并为一个 decorate(lambda_or_memfn) 函数(使用模板专业化、if constexpr 或其他)。例如

decorate([](int i) { return i + 1; });
decorate(&Worker::work);

即基本上我想要 decorate_memfn(&Worker::work) 而不是 decorate_memfn<&Worker::work>()。问题是

我知道 C++20 可以提供帮助,但不幸的是我仍然坚持使用 C++17。

非常感谢任何提示!

首先,您的 decorate_lambda 有问题:如果您使用有状态可调用对象调用它,它会无声地中断。作为一个简单的检查,您可以仅在 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

您可以使用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>);