簡體   English   中英

是否可以在lambda中捕獲可變數量的參數?

[英]Is it possible to capture a variable number of parameters in a lambda?

請考慮以下示例。

  1. 函數takeOnlyVoidFunction接受帶有零參數的函數並簡單地執行它。
  2. 函數takeVariableArguments接受可變數量的參數,並使用這些參數執行該函數。
  3. 函數captureVariableArgs嘗試將第二個函數轉換為第一個函數可以接受的lambda形式,但不進行編譯。

如何使函數captureVariableArgs編譯並顯示將具有可變數量的參數的函數轉換為不帶參數的閉包的正確行為?

#include <stdio.h>
#include <functional>

void takeOnlyVoidFunction(std::function<void()> task) {
    task();
}

template<typename _Callable, typename... _Args>
    void takeVariableArguments(_Callable&& __f, _Args&&... __args) {
     __f(__args...);
}

// How can I make this function compile?
template<typename _Callable, typename... _Args>
    void captureVariableArgs(_Callable&& __f, _Args&&... __args) {
    takeOnlyVoidFunction([=]() { __f(__args...);});
}

void normalFunction(int a, int b) {
    printf("I am a normal function which takes params (%d,%d)\n", a, b);
}

int main() {
    int a = 7;
    int b = 8;
    takeVariableArguments(normalFunction, a, b);
    takeOnlyVoidFunction([=](){ normalFunction(a,b);});
    captureVariableArgs(normalFunction, a, b);
}

我正在運行gcc 4.9.2 這是我看到的編譯器錯誤。

g++ -std=c++11    Test.cc   -o Test
Test.cc: In instantiation of ‘captureVariableArgs(_Callable&&, _Args&& ...)::<lambda()> [with _Callable = void (&)(int, int); _Args = {int&, int&}]’:
Test.cc:16:38:   required from ‘struct captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>’
Test.cc:16:50:   required from ‘void captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]’
Test.cc:28:45:   required from here
Test.cc:16:34: error: variable ‘__f’ has function type
     takeOnlyVoidFunction([=]() { __f(__args...);});
                                  ^
Test.cc:16:34: error: variable ‘__f’ has function type
Test.cc: In instantiation of ‘struct captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>’:
Test.cc:16:50:   required from ‘void captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]’
Test.cc:28:45:   required from here
Test.cc:16:34: error: field ‘captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>::<__f capture>’ invalidly declared function type
In file included from Test.cc:2:0:
/usr/include/c++/4.9/functional:2418:7: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>; <template-parameter-2-2> = void; _Res = void; _ArgTypes = {}]’, declared using local type ‘captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>’, is used but never defined [-fpermissive]
       function<_Res(_ArgTypes...)>::
       ^

更新 :演示此問題的更簡單的示例。

#include <stdio.h>

// How can I make this function compile?
template<typename _Callable>
void captureVariableArgs(_Callable&& __f) {
    takeOnlyVoidFunction( [=]{ __f(); } );
}

void normalFunction() {
    printf("I am a normal function\n");
}

int main(){
    captureVariableArgs(normalFunction);
}

文章中的代碼可以使用最新的clang&MSVC編譯器很好地編譯,但是所有gcc都拒絕對其進行編譯。 因此,這似乎是gcc中的錯誤。 不過,我找到了一種使gcc滿意的方法:只是不要在可調用參數上使用“通用引用”,如下所示:

template<typename _Callable, typename... _Args>
int captureVariableArgs(_Callable _f, _Args&&... _args) {
    return takeOnlyVoidFunction([=]() { _f(_args...);});
}

不過,我無法解釋為什么gcc不接受您的版本。 我不熟悉gcc樣式的錯誤報告,也無法從錯誤消息中提取出真正的原因。 但是我認為解決方法是可以的,因為在這種情況下,我在“通用引用”中看不到任何值。 實際上,我也不明白為什么還要在args上使用它。

作為GCC的另一個可能的解決方法,您可以使用std::bind來代替lambda:

template <typename F, typename... Args>
auto captureVariable(F&& f, Args&&... args)
{
    return std::bind(std::forward<F>(f), std::forward<Args>(args)...);
}

這在GCC 4.9.3下對我有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM