传递条件作为参数

问题描述:

首先要解释什么是我想要做的事:传递条件作为参数

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

一个例子使用标准库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

你应该做的是创造,测试你的条件的功能,然后将指针传递给该函数的参数。有关如何执行此操作的详细信息/教程,请参阅http://www.cprogramming.com/tutorial/function-pointers.html

+0

但是对于函数指针,您需要传递边界,或者为每个需要的边界创建一个函数 - 普通函数不带任何状态。 – 2010-07-24 06:25:39

+0

是的,这正是我应该做的字符串解析。或者我错过了什么? – Johnny 2010-07-24 06:31:39

传递一个函数来代替Foo。然后您可以通过等待调用该函数来“延迟”表达式的执行。

这样做的合理方法是将一个仿函数和对象的行为类似于函数传递给被调用的函数,被调用的函数将调用仿函数在循环的每次迭代中重新评估条件。

解析字符串行不通的;被调用函数不能访问调用函数的局部变量。

+0

字符串方法基于这样的事实,即用于用户的数字输入,因此只有一个变量需要检查,可以作为参考传递,并且如果输入是关于条件的。否则functor是我需要的,谢谢,投票了。 – Johnny 2010-07-24 06:42:38

这被称为函数式编程。

这里代码段使用boost ::凤http://www.boost.org/doc/libs/1_43_0/libs/spirit/phoenix/doc/html/phoenix/starter_kit.html

using namespace boost::phoenix; 

Foo(x, (cref(x) < 3)); 
// (cref(x) < 3) is expression that creates function object 

template<class C> // condition is a monster, make it generic 
void Foo(int &num, C condition) 
{ 
    while(!condition()) // notice you call condition as function 
    { 
     rand(num); 
    } 
} 

正如其他人所说,通过仿函数对象进入美孚()。 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

你可以做到这一点没有模板或升压(一个称之为“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