2010-07-24 55 views
4

首先要解釋什麼是我想要做的事:傳遞條件作爲參數

void Foo(int &num, bool condition); 

Foo(x, x > 3); 

此代碼基本上都會評估條件的布爾調用函數之前,然後通過純粹的真或假。我正在尋找一種方式,使其通過自身的條件,所以我可以做這樣的事情:

void Foo(int &num, bool condition) 
{ 
    while(!condition) 
    { 
     num = std::rand(); 
    } 
} 

我知道有可能是使含有條件的字符串和解析後一種解決方法,並我現在正在研究它,但我覺得它效率低下。被接受的答案將是解析包含條件的字符串旁邊的任何其他方式的解答,或者解釋這種傳遞條件的方式是不可能的答案。

在此先感謝

+1

有沒有更大的圖片,所以我們可以在真實情況下看到'Foo'(假裝它可以正常工作)?另外,當它是一個引用時,你傳遞'x'作爲參數,而不是'x'的地址。 – GManNickG 2010-07-24 06:06:12

+1

如果'std :: rand()'注意它返回一個int並且不帶任何參數。 – 2010-07-24 06:10:46

+0

是的,我沒有檢查它,我只是寫它來給出一個想法應該如何工作。我很遺憾代碼很可笑,但是我在幾分鐘之內直接在這裏寫了它。 @GMan - 我可以複製和粘貼代碼,但它可能會錯過某些部分,所以我只是想說明一下。它應該做的是一直要求用戶輸入一次又一次,只要條件不被尊重。 – Johnny 2010-07-24 06:30:57

回答

11

一個例子使用標準庫functor

#include <functional> 

template<class UnaryPred> void func(int& num, UnaryPred predicate) { 
    while(!predicate(num)) num = std::rand(); 
} 

void test() { 
    int i = 0; 
    func(i, std::bind1st(std::greater<int>(), 3)); 
} 

見什麼C++已經爲您提供了即用的盒上<functional>的文檔。

如果你的編譯器有足夠的支持(例如GCC 4.5或VC10),你也可以去lambda functions。例如。使用相同的func()如上:

func(i, [](int num) { return num > 3; }); 
+0

這很可能正是我所需要的,並且很可能是一個被接受的答案,只是我想檢查一下,看看它是如何工作的。 關於lambda函數(我正在使用VC10),我該如何在函數中調用它? – Johnny 2010-07-24 06:46:33

+0

與第一個例子中的'func()'完全一樣:'predicate(someNumber)'。 lambda表達式也會在後臺生成一個函子,只是編譯器會爲你做這件事,並且你會得到更好的語法。 – 2010-07-24 06:53:02

+0

哦,對不起,我認爲後面的代碼是獨立於上面的代碼。所以這只是func的簡化調用?謝謝! – Johnny 2010-07-24 06:56:09

2

你應該做的是創造,測試你的條件的功能,然後將指針傳遞給該函數的參數。有關如何執行此操作的詳細信息/教程,請參閱http://www.cprogramming.com/tutorial/function-pointers.html

+0

但是對於函數指針,您需要傳遞邊界,或者爲每個需要的邊界創建一個函數 - 普通函數不帶任何狀態。 – 2010-07-24 06:25:39

+0

是的,這正是我應該做的字符串解析。或者我錯過了什麼? – Johnny 2010-07-24 06:31:39

1

傳遞一個函數來代替Foo。然後您可以通過等待調用該函數來「延遲」表達式的執行。

2

這樣做的合理方法是將一個仿函數和對象的行爲類似於函數傳遞給被調用的函數,被調用的函數將調用仿函數在循環的每次迭代中重新評估條件。

解析字符串行不通的;被調用函數不能訪問調用函數的局部變量。

+0

字符串方法基於這樣的事實,即用於用戶的數字輸入,因此只有一個變量需要檢查,可以作爲參考傳遞,並且如果輸入是關於條件的。否則functor是我需要的,謝謝,投票了。 – Johnny 2010-07-24 06:42:38

1

正如其他人所說,通過仿函數對象進入美孚()。 STL通常使用這種方法。例如:

template< class Func > 
void Foo(int &num, Func condition) 
{ 
    while(!condition()) 
    { 
     rand(num); 
    } 
} 

struct GreaterThanThree 
{ 
    int& _num; 
    GreaterThanThree(int &num) : _num(num) {} 
    bool operator()() const { return (_num > 3); } 
}; 

Foo(x, GreaterThanThree(x)); 
+0

嗯,我不僅僅使用三種以上的情況,因爲這是一個包含常用條件輸入的庫。否則,我對C++的高級可能性仍然很沒經驗,所以我得問一下結構GreaterThanThree代表什麼(它不是一個通常的結構)。可能你可以給出一個關於這樣的結構或類似的參考的鏈接? – Johnny 2010-07-24 06:36:00

+0

@Johnny:這是一個函子。 @Remy:爲了讓函子具有可變狀態,'Foo'應該通過引用來使用'Func&condition'。 – rwong 2010-07-24 07:02:16

+0

@rwong:當然,如果你需要多次傳入相同的函子對象。但這並不常見。我只見過與臨時實例一起使用的函數,與我所展示的類似。 – 2010-07-27 03:08:23

1

你可以做到這一點沒有模板或升壓(一個稱之爲「C風格」評論者,這是正確的,我想)。

/* have Foo take a pointer to a function that returns bool */ 
void Foo(int &num, bool (*fcn)(int)) 
{ 
    while(!fcn(num)) 
    { 
     num = std::rand(); 
    } 
} 

/* You can have all the Comparators you want, 
    as long as they have the same signature */ 
bool ComparatorOne(int x) { return x > 3 ? true : false; } 

bool ComparatorTwo(int x) { return x < 10 ? true : false; } 

/* and this is how you call it */ 
int n; 
Foo(n, ComparatorOne); 
Foo(n, ComparatorTwo); 

編輯

請注意,您比較可以採取不同的參數,只要他們是一致的。

+0

我很抱歉,我的問題不清楚,但我需要它的任何形式的條件,而不僅僅是整數。它必須是普遍的。無論如何,感謝這樣的解決方案的提示和例子,投票! – Johnny 2010-07-24 07:17:20

+0

這是C風格的解決方案,不是C++風格的解決方案。 C++會使用函數或lambda(如果您的編譯器支持它們)。 – Sjoerd 2010-07-24 07:23:53

+0

我同意這是一個C風格的解決方案,但它的工作原理很容易理解。 – egrunin 2010-07-24 07:25:07