Передача условия в качестве параметра - PullRequest
4 голосов
/ 24 июля 2010

Прежде всего, чтобы объяснить, что я пытаюсь сделать:

void Foo(int &num, bool condition);

Foo(x, x > 3);

Этот код в основном оценивает bool условия перед вызовом функции, а затем передает pure true или false.Я ищу способ заставить его пройти само условие, чтобы я мог сделать что-то вроде этого:

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

Я знаю, что может быть обходной путь, передав строку, содержащую условие, и проанализировав последнееи я сейчас над этим работаю, но считаю это довольно неэффективным способом.Принятым ответом будет тот, который объясняет решение любым другим способом, кроме того, который разбирает строку, содержащую условие, или ответ, который разъясняет, что этот способ передачи условий невозможен.*

Ответы [ 7 ]

11 голосов
/ 24 июля 2010

Один пример использования стандартной библиотеки 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));
}

См. Документацию по <functional>, чтобы узнать, что C ++ уже предоставляет вам из коробки.

Если ваш компилятор имеет достаточную поддержку (например, GCC 4.5 или VC10), вы также можете перейти к лямбда-функциям . Например. используя тот же func(), что и выше:

func(i, [](int num) { return num > 3; });
3 голосов
/ 24 июля 2010

это называется функциональным программированием.

здесь фрагмент с использованием boost :: phoenix 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);
    }
}
2 голосов
/ 24 июля 2010

Вероятный способ сделать это - передать функтор - и объект, который ведет себя как функция - в вызываемую функцию, а вызываемая функция вызовет функтор для повторной оценки условия на каждой итерации цикла.

Разбор строки не сработает; вызываемая функция не имеет доступа к локальным переменным вызывающей функции.

2 голосов
/ 24 июля 2010

Что вам нужно сделать, это создать функцию, которая проверяет ваше состояние, а затем передает указатель на эту функцию в качестве параметра. См. http://www.cprogramming.com/tutorial/function-pointers.html для получения подробной информации / учебники о том, как это сделать.

1 голос
/ 24 июля 2010

Вы можете сделать это без шаблонов или повышения (комментатор назвал это "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);

Редактировать

Обратите внимание, что ваш Comparator может принимать другой набор параметров, если они согласованы.

1 голос
/ 24 июля 2010

Как уже говорили другие, передайте объект-функтор в Foo (). 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)); 
1 голос
/ 24 июля 2010

Передайте функцию вместо Foo.Затем вы можете «задержать» выполнение выражения, ожидая вызова этой функции.

...