Функция C ++, которая принимает в качестве аргументов массив, предикат и оператор и применяет оператор к элементу массива, где предикат удовлетворяется. - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь написать функцию, как описано в заголовке. Я создал шаблонный массив dynamic c под названием queue, и мне нужно создать функцию, которая проверяет каждый элемент этой очереди, удовлетворяется ли предикат, переданный аргументом; если это так, мне нужно применить оператор к этому элементу, также переданному аргументом.

Прежде всего мне, вероятно, нужно объяснение ... предикат должен быть унарным, чтобы это могло быть что-то вроде «isdi git» или «isalpha», верно? и в качестве оператора это может быть что-то вроде простого постинкремента ++. Основная проблема в том, что я действительно понятия не имею, как передавать операторы и предикаты в качестве параметров в функции.

Если я понял запрос, вот что я пытался сделать, но, конечно, не работает ... Кто-нибудь помогает?

template<typename L, typename OPERATOR>

void change_if(queue<L> &que, bool (*f)(L), OPERATOR op) {

    for(int i=0; i<que._size-1; i++) {
        if ((*f)(que._queue[i]))
            que._queue[i] = op(que._queue[i]);
    }
}

int main(){
    //as constructor, 3 is referred to size of the queue and 99 to the values.
    queue<int> q(3, 99);

    change_if(q, isdigit, ++);

}

1 Ответ

0 голосов
/ 29 мая 2020

Сначала я бы предложил передать предикат также с предполагаемым типом, чтобы вы также могли передавать лямбды, т.е.

template<typename L, typename P, typename OP>
void change_if(queue<L> &que, P pred, OP op) {
  for(...)
    if(pred(que._queue[i]))
       que._queue[i] = op(que._queue[i]);
}

Ваша идея немного противоречива, поскольку вы выполняете присваивание (que._queue[i] = op(que._queue[i]); ), а затем пришла идея, что op должно быть чем-то вроде оператора постинкремента.
Оба вместе будут сводиться к a = a++, что не имеет никакого эффекта.

Вы могли бы go один из двух способов:

  1. воспринимайте «op» как функцию, получающую элемент и возвращающую измененный, т.е. L op(const L&l) { return l+1; }. Затем используйте приведенный выше код и вызовите
    change_if(q, [](auto && l) { return std::isdigit(l); }, [](auto && l) { return l + 1});
  2. подумайте о «op» как о функции, изменив полученный элемент, т.е. void op(L&l) { l++;}. Затем используйте if(pred(...)) op(que._queue[i]) и вызовите
    change_if(q, [](auto && l) { return std::isdigit(l); }, [](auto && l) { l++; });

В качестве побочного примечания: вы не можете просто взять адрес std::isdigit, так как он перегружен, поэтому я заключил вызов в лямбду здесь .

Еще одно примечание: я не знаю вашу реализацию очереди, но < size-1 в условии for l oop выглядит так, будто вам не хватает последнего элемента.

...