簡體   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