簡體   English   中英

指向具有不同參數的成員函數的指針的容器

[英]Container for pointers to member functions with different arguments

我到處都在尋找(現代C ++設計和合作),但是我找不到一種好方法來存儲一組接受不同參數並在不同類上運行的回調。 我之所以需要這樣做,是因為我希望應用程序的每個對象都可以將其方法之一的執行推遲到主Clock對象上,該主Clock對象可以跟蹤當前時間,可以在適當的時候調用此方法。 我所針對的代碼大致如下:

class1void executeAction1Deferred(int time, int arg1, bool arg2)方法中,其中time是將來所需的執行時間,應該是這樣的:

Clock::defer(time, Class1::action1, this, arg1, arg2);

Clock::defer(??? what signature ????) ,代表此Task的對象存儲在優先級隊列中,其中時間是鍵。 然后,將遍歷每個“ Clock ”任務列表,然后執行需要在該任務中運行的任務。 請注意,我已經將“ defer”用作靜態函數,因為我打算使用Singleton的Clock對象,但是它也可以是成員函數,這只是選擇的問題。

我曾考慮過使用void*來保留可變數量的參數,但是讓我的action1()方法接受void*確實很糟糕,這還因為每次我直接使用此函數時都需要為參數構造一個結構而不會推遲。

過去,我多次遇到過這個問題,但從未找到真正合適的解決方案。 請注意,由於這是一個小型的多平台項目,因此對於缺乏經驗的程序員來說,構建簡單的可以擴展的項目至關重要,我不想使用boost。 但是,我們處理的平台的每個編譯器都有std::tr1綁定。 問題是:如何定義一個泛型函數的容器,每個泛型函數接受可變數量的參數(最多N〜5個),並且是不是從公共虛類派生的對象的不同成員方法? 謝謝

使用std::function<void()>存儲調用,然后使用可變參數模板參數轉發和綁定函數參數:

class Clock
{
    vector<function<void()>> tasks;

    template<class F, class... Args>
    void defer(F f, Args&&... args)
    {
        tasks.push_back(bind(f, forward<Args>(args)...);
    }

}

void f(A a, B b);

int main()
{
    A a;
    B b;

    Clock c;
    c.push_back(f, a, b);
}

另請參見std::bindstd::mem_fun

在C ++ 11中,存儲std::function<void()> 您可以使用std::bind從其他簽名之一創建函數,例如:

std::vector<std::function<void()>> deferred;
deferred.push_back(std::bind(&Class1::action1, this, arg1, arg2));

// later...
for (auto f : deferred) f();

如果沒有C ++ 11,則Boost具有非常相似的functionbind模板。 我認為它們可能也存在於TR1中,盡管我沒有任何歷史參考可查。

如果Boost確實不是一個選項(而TR1不提供這些選項),那么我強烈建議您將其設為一個選項; 否則,請使用Boost作為實現此方法的示例。 沒有可變參數的模板,它將變得非常毛茸茸。

(並且由於您提到了Modern C ++ Design,因此請閱讀類型列表中的部分;這就是不使用可變參數模板的方式)。

由於您的回調將包括其提供的參數而被推遲,因此實際的簽名將為void() ,即Clock對象將不會自行提供參數,也無需評估結果。 因此,通常您會希望將成員函數指針(或其他函數指針)與所需的參數綁定在一起,並將結果(函數對象)傳遞給時鍾。 這是boost::bind / std::tr1::bindboost::function / std::function<void()>出現的地方-或C ++ 11 lambdas:

Clock::defer(time, boost::bind(&Class1::action1, this, arg1, arg2));
//C++11 lambda:
Clock::defer(time, [=](){action1(arg1, arg2);} );

但是您正在做的事情已經完成-看一下Boost.Asio計時器:

boost::asio::basic_deadline_timer timer(ioService, expiryTime);
timer.async_wait([=](){action1(arg1, arg2);} //perform action1 when the timer is done

暫無
暫無

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

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