2012-02-03 22 views
1

我正在考慮做一個take_timing函數,該函數將傳遞給它的任何函數的時間。通過任何函數這意味着這個回調所需的參數是調用者未知的。這將需要回調的參數。但是因爲它不知道如何調用它,所以需要另一個回調函數,函數用戶編寫的回調的調用者。存根會是這樣的:在C和C++中回調一個具有先前未知參數的函數

void take_timing(
    void (*callback)(), 
    void (*caller(void (*callback)(),void* args_struct), 
    void* args_struct 
) 
{ 
    // Start timer 

    caller(callback,args_struct); 

    // Stop timer, read timings, record... 
} 

void some_caller(void (*callback)(),void* args_struct) 
{ 
    // Cast "callback" to function signature 
    // Cast args_struct to some struct with args 
    // Call the callback with correct args signature 
} 

所以說到我的問題:

  1. 這可能嗎?
  2. 它可以使用可變參數列表來簡化它嗎?怎麼樣?我對此很無奈......
  3. 有沒有更好的方法呢?或者,對於每一個特定情況,只需要take_timing就好?
  4. 有沒有OOP設計模式用於C++?

我自己放棄了這個,但是出於好奇,這可能是一些非常有用的見解。

+0

額外抽象的價值是什麼?爲什麼不只用一個上下文指針來獲取已知的回調函數類型?我猜這裏我沒有看到增值服務。 – 2012-02-03 19:26:49

回答

4

只需要一個仿函數作爲模板參數。喜歡的東西:處理這種

template<typename F> 
nanoseconds take_timing(F f) { 

    auto start = high_resolution_clock::now(); 
    f(); 
    auto end = high_resolution_clock::now(); 
    return end - start; 
} 

long long factorial(int i); 

take_timing([](){factorial(20);}); // wrap call to function taking arguments in zero-argument lambda 
+0

嗯,這真的很棒,完美工作,不是介意令人難以置信,閱讀,理解和使用非常簡單。讓我們拭目以待,看看是否有一種簡單的C方法來做到這一點。 – 2012-02-03 20:55:28

3

您正在尋找varargs的支持,該支持確實存在於ANSI C中。如果您搜索它,將會產生巨大的Google搜索結果。這是一個隨機的:http://www.eskimo.com/~scs/cclass/int/sx11b.html

+0

好吧,但有沒有辦法將'varargs'傳遞給另一個函數?在我們的例子中,'take_timing'得到'va_list'。但是它將如何調用'caller'並將參數從'va_list'傳遞給它? – 2012-02-03 20:58:48

+0

如果被調用的函數也可以帶參數的va_list,那麼是的。 IE,如果父函數是foo(va_list args),那麼它肯定可以很容易地調用bar(va_list args),傳遞相同的參數集合(或者先使用它)。 – 2012-02-03 21:33:15

+0

我認爲它使它成爲一個有效的解決方案,儘管令人難以置信。事實上,這正是我第一次想到的,但我不確定傳遞宏處理的'va_list'是否有效。而且,當開始編碼時,我發現它並不是很好的可用性設計,至少對我來說不是這樣。 – 2012-02-03 21:46:07