簡體   English   中英

C++11 lambda 作為成員變量?

[英]C++11 lambda as member variable?

可以將 lambda 定義為 class 成員嗎?

例如,是否可以使用 lambda 而不是 function object 來重寫下面的代碼示例?

struct Foo {
    std::function<void()> bar;
};

我想知道的原因是因為以下 lambda 可以作為 arguments 傳遞:

template<typename Lambda>
void call_lambda(Lambda lambda) // what is the exact type here?
{ 
    lambda();
}

int test_foo() {
    call_lambda([]() { std::cout << "lambda calling" << std::endl; });
}

我想如果 lambda 可以作為 function 參數傳遞,那么也許它們也可以存儲為成員變量。

經過更多的修補后,我發現這有效(但它有點毫無意義):

auto say_hello = [](){ std::cout << "Hello"; };
struct Foo {
    typedef decltype(say_hello) Bar;
    Bar bar;
    Foo() : bar(say_hello) {}
};

A lambda just makes a function object, so, yes, you can initialize a function member with a lambda. 這是一個例子:

#include <functional>
#include <cmath>

struct Example {

  Example() {
    lambda = [](double x) { return int(std::round(x)); };
  };

  std::function<int(double)> lambda;

};

模板可以在沒有類型擦除的情況下實現,但就是這樣:

template<typename T>
struct foo {
    T t;
};

template<typename T>
foo<typename std::decay<T>::type>
make_foo(T&& t)
{
    return { std::forward<T>(t) };
}

// ...
auto f = make_foo([] { return 42; });

重復每個人已經公開的 arguments : []{}不是類型,因此您不能像您嘗試的那樣將其用作例如模板參數。 使用decltype也是不確定的,因為 lambda 表達式的每個實例都是具有唯一類型的單獨閉包 object 的表示法。 (例如上面f的類型不是foo<decltype([] { return 42; })> 。)

有點晚了,但我在這里的任何地方都沒有看到這個答案。 如果 lambda 沒有捕獲 arguments,則可以將其隱式轉換為指向 function 的指針,並返回相同的 ZDBC11CAA5BDA999 類型。

例如,以下程序可以正常編譯並執行您期望的操作:

struct a {
    int (*func)(int, int);
};

int main()
{
    a var;
    var.func = [](int a, int b) { return a+b; };
}

當然,lambdas 的主要優點之一是捕獲子句,一旦添加了它,那么這個技巧將根本不起作用。 如上所述,使用 std::function 或模板。

#include <functional>

struct Foo {
    std::function<void()> bar;
};

void hello(const std::string & name) {
    std::cout << "Hello " << name << "!" << std::endl;
}

int test_foo() {
    Foo f;
    f.bar = std::bind(hello, "John");

    // Alternatively: 
    f.bar = []() { hello("John"); };
    f.bar();
}

“如果 lambda 可以作為 function 參數傳遞,那么也可以作為成員變量傳遞”

第一個是肯定的,您可以使用模板參數推導或“自動”來這樣做。 第二個可能不是,因為您需要知道聲明點的類型,並且前兩個技巧都不能用於此。

一種可能有效但我不知道是否有效的方法是使用 decltype。

只要 lambda 是常數(沒有閉包),你可以這樣做:

#include <iostream>

template<auto function>
struct Foo
{
    decltype(function) bar = function;
};

void call_lambda(auto&& lambda)
{
    lambda();
}

int main()
{
    Foo<[](){ std::cout << "Hello"; }> foo;
    foo.bar();
    call_lambda(foo.bar);
}

https://godbolt.org/z/W5K1rexv3

或者我們可以應用演繹指南使其適用於所有 lambda:

#include <iostream>

template<typename T>
struct Foo 
{
    T bar;
};

template<typename T>
Foo(T) -> Foo<std::decay_t<T>>;

void call_lambda(auto&& lambda)
{
    lambda();
}

int main()
{
    Foo foo([](){ std::cout << "Hello"; });
    foo.bar();
    call_lambda(foo.bar);
}

https://godbolt.org/z/xv97Ghj7T

暫無
暫無

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

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