2011-10-21 47 views
1

我想知道如果在C++中可以通過將第n個參數的值設置爲某個值(要在運行時確定)從一個帶n個參數的函數中獲取(n-1)個參數?是否可以通過將一個參數設置爲一個固定值來從n參數函數中獲取(n-1)-argument函數?

E.g.我想這樣做如下:

float foo(float a, float b, float c){ 
    // do some stuff 
} 

float bar(float x, float y, float f(float q, float r)){ 
    return f(x,y); 
} 

int main(){ 
    double (*function)(float, float); 
    float some_value; 
    // somehow determine some_value, e.g. read from stdin. 
    // Now I would like to set function something along the lines of: 
    function = foo(. , . , some_value) 
    return bar(123, 456, function); 
} 

概念,foo是函數的家人c索引,即一個家庭的功能foo_c (float a, float b)(讀「foo_c」爲「富標c」在這裏),和我想分別通過foo_c指向它的指針作爲參數bar

這在C++中完全可能嗎? 據我所知,對於上面的函數指針來說這是不可能的。有沒有其他的方式來做這樣的事情?

我簡要地考慮做foo一個函數模板,但我想設置它在運行時的第三個參數,這將無法正常工作。

顯而易見的解決方案當然是修改bar以便將float f(float q, float r, float t)作爲第三個參數,但這會使代碼重複使用少得多(並且看起來不那麼優雅)。我會想通過其他功能bar爲好,其中一些只需要兩個參數,三個以上的,或不同類型的參數,這是我需要以某種方式將它們傳遞給bar之前,設置成固定值。

我還沒有完全弄清楚,在這種情況下,我是否可以使bar爲模板函數,沿着template <typename T, typename S> float bar(float x, float y, T f(float a, float b, S param), S parameters)的行,然後使用類似bar <double *(float, float, float), float> (123, 456, function, parameters)的方式調用它。沿着這些線會有什麼工作嗎?

+2

對於你的Google-fu:這被稱爲*部分應用程序*,並且受到大多數現代編程語言的本機支持,特別是那些聲稱促進函數式編程的。 –

+0

通過'std :: bind'部分應用。 –

+0

順便說一下,'bar'的'f'參數是一個返回'float'的函數,但是您已經定義了函數指針'function'來返回'double'。 –

回答

4

你不能用函數指針做到這一點,但是,它可以用函數對象來完成。如果您使用C++ 03,我建議您查看Boost.Bind。如果您使用的是C++ 11,則std::bind是標準的一部分,並且工作方式相同。 C++ 11還引入了內置的lambdas,它們可以完成你正在嘗試的任務。

爲了存儲綁定或lambda的結果,您可以在C++ 11中使用C++ 03或std::function中的Boost.Function

這個例子是你會怎麼做它在C++ 03。

float foo(float a, float b, float c){ 
    // do some stuff 
} 

float bar(float x, float y, boost::function<float(float,float)> f){ 
    return f(x,y); 
} 

int main(){ 
    boost::function<float(float,float)> func; 
    float some_value; 
    // somehow determine some_value, e.g. read from stdin. 
    // Now I would like to set function something along the lines of: 
    func= boost::bind(foo, _1, _2, some_value); 
    return bar(123, 456, func); 
} 

在C++ 11,你可以使用綁定和功能的標準版本,或者你可以使用拉姆達功能:

float foo(float a, float b, float c){ 
    // do some stuff 
} 

float bar(float x, float y, std::function<float(float,float)> f){ 
    return f(x,y); 
} 

int main(){ 
    std::function<float(float,float)> func; 
    float some_value; 
    // somehow determine some_value, e.g. read from stdin. 
    // Now I would like to set function something along the lines of: 
    func= [some_value](float x, float y) { return foo(x,y,some_value); }; 
    return bar(123, 456, func); 
} 
+0

啊,lambda表達式 - 非常漂亮!非常感謝您的幫助!作爲一個方面說明,似乎可以在Mac上使用C塊完成同樣的事情 - 然後它會是float(^ func)(float,float)= ^(float x,float y){return foo(x ,Y,SOME_VALUE);};' – matt

4

你不能用函數指針那樣做,但你可以用類似功能的對象來做到這一點。 C++ 11爲你提供了std::bindstd::function(也包括lambda表達式,但我不太瞭解他們的例子)。在C++ 03中,boost::bindboost::function非常相似。

float foo(float a, float b, float c){ 
    // do some stuff 
} 

float bar(float x, float y, function<float(float, float)> f){ 
    return f(x,y); 
} 

int main(){ 
    float some_value; 
    // somehow determine some_value, e.g. read from stdin. 

    return bar(123, 456, bind(foo,_1,_2,some_value)); 
} 
相關問題