簡體   English   中英

將閉包作為參數傳遞給構造函數C ++

[英]Passing a closure as a parameter to a constructor c++

在下面的代碼中,我想擺脫使用各種類型的函數指針的怪異構造函數以及必須保存的參數列表(以及保存所有這些內容所需的所有成員變量),以及取而代之的是使用閉包來完成所有操作,讓Event保留一個類似於Closure closure;成員變量Closure closure; 有沒有辦法使用C ++ 0x中的閉包來做到這一點?

#include <iostream>
#include <list>
#include <functional>
#include <algorithm>

class Event
{
    std::function<double(double, double)> func1;
    bool func1Defined;
    double double1, double2;

    std::function<double(int, int, int)> func2;
    bool func2Defined;
    int int1, int2, int3;
public:
    void setFalse()
    {
        func1Defined = false;
        func2Defined = false;
    }
    Event(std::function<double(double, double)> func, double double1, double double2)
    {
        setFalse();
        func1 = func;
        func1Defined = true;
        this->double1 = double1;
        this->double2 = double2;
    }

    Event(std::function<double(int, int, int)> func, int int1, int int2, int int3)
    {
        setFalse();
        func2 = func;
        func2Defined = true;
        this->int1 = int1;
        this->int2 = int2;
        this->int3 = int3;
    }

    void run()
    {
        double ret = 0;
        if (func1Defined) ret = func1(double1, double2);
        else if (func2Defined) ret = func2(int1, int2, int3);
        /* do something with ret */
        std::cout << ret << "\n";
    }
};

double twoDoubleParam(double a, double b)
{
    return a + b;
}

double threeIntParam(int a, int b, int c)
{
    return (a + b) / c;
}

int main(int argc, char* argv[])
{
    std::list<Event> events;
    events.push_back(Event(*twoDoubleParam, 1.0, 3.5));
    events.push_back(Event(*threeIntParam, 2, 4, 2));
    std::for_each(events.begin(), events.end(), [&](Event event)
    {
        event.run();
    });

    int y;
    std::cin >> y;
    return 0;
}

最好不要加葯,但是如果加葯是最好的/只是簡便的方法,我想知道如何做。

看來您的Event應該只持有std::function<double()> :與是否使用lambda無關,您想綁定參數以創建一個無效函數(據我所知;是否存在是每個調用的實際參數,您顯然會在std::function<Signature>使用相應的簽名。

假設您的Event具有std::function<double()>類型的成員fun ,並且構造函數類似

template <typename Fun>
Event::Event(Fun fun): fun(fun) {}

您可以使用

events.emplace_back([](){ return twoDoubleParam(1.0, 3.5); });
events.emplace_back(std::bind(&threeIntParam, 2, 4, 2));

兩種方法都可以使用std::bind()或lambda。 我只是混合使用以獲得每個。 顯然,如果使用lambda且參數不是常量而是值,則可以使用[=](){ ... }按值捕獲閉包值。

使用std::bind執行此操作。 參見此處: http : //en.cppreference.com/w/cpp/utility/functional/bind

在VS2012 / 13中,以及更新的GCC中。 如果需要,也可以將返回值直接分配給std::function<void()>

看起來你想要std::bind

std::function<void()> func;

...

Event(std::function<double(double, double)> func, double d1, double d2) {
    func = std::bind(func, d1, d2);
}

// Repeat for the three ints

另外,您也可以讓用戶能夠提供任何functor / args組合並為其綁定它們,例如std::thread的構造函數:

template<typename F, typename... Args>
Event(F&& f, Args&&... args) {
    func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
}

要么

template<typename F, typename... Args>
Event(Args&&... args) {
    static_assert(sizeof...(Args) > 1, "Event() requires more than 1 argument");
    func = std::bind(std::forward<Args>(args)...);
}

您可以使用std::bindstd::function

class Event {
    function<double()> func;
public:
    template <typename H, typename... Args>
    Event(H &&f, Args&&... args) 
          : func(bind(std::forward<H>(f), std::forward<Args>(args)...)) {}

    void run()
    {
        double ret = func();
        std::cout << ret << "\n";
    }
};

double twoDoubleParam(double a, double b) {
    return a + b;
}

double threeIntParam(int a, int b, int c) {
    return (a + b) / c;
}

int main(int argc, char* argv[]) {
    std::list<Event> events;
    events.push_back(Event(twoDoubleParam, 1.0, 3.5));
    events.push_back(Event(threeIntParam, 2, 4, 2));
    std::for_each(events.begin(), events.end(), [&](Event &event)
    {
        event.run();
    });
}

產量

4.5
3

現場代碼

暫無
暫無

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

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