Изменить операцию во время выполнения в C ++ - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть небольшая проблема под рукой.Предположим, что есть условие if только с 2 операндами, но я хочу сделать операцию динамической.

void somFunc()
{
  if(a && b) /*1*/
  {
  }
  else if(a1 && b1) /*2*/
  {
  }
  else if(a || b) /*3*/
  {
  }
  else if(a1 || b1) /*4*/
}


В основном, 1 и 3 имеют одинаковые параметры с разными операциями, аналогично для 2 и 4.Я хочу сократить эти 4 операции до 2.
Я хочу знать, есть ли способ сделать oper динамическим.Предположим, у нас есть только 2 операции && и ||
Могу ли я использовать шаблоны каким-либо образом?
Если кто-то хочет знать, зачем мне это нужно, есть условия if внутри большого if / else.Если я как-то достигну этого, я уменьшу условия наполовину.

Ответы [ 5 ]

0 голосов
/ 18 декабря 2018

Вы можете сделать это также с помощью CRTP :

#include <iostream>
#include <string>
#include <memory>

template<class T>
class Operation
{
public:
   bool eval(bool a, bool b)
   {
      return this->impl().eval(a,b);
   }
private:
   T& impl() { return static_cast<T&>(*this); }
};

class AndOperation : public Operation<AndOperation>
{
public:
   bool eval(bool a, bool b)
   {
      return a && b;
   }
};

class OrOperation : public Operation<OrOperation>
{
public:
   bool eval(bool a, bool b)
   {
      return a || b;
   }
};

int main()
{
  AndOperation andOp;
  auto anonOp = std::make_unique<OrOperation>();
  std::cout << andOp.eval(true, true) << std::endl;
  std::cout << anonOp->eval(false,false);
}

см. живой пример здесь

Что такоепреимущества CRTP перед виртуальным наследованием ?CRTP - это случай статического полиморфизма .Вот некоторые ссылки:

Время компиляции против полиморфизма во время выполнения в C ++. Преимущества / недостатки

Какова мотивация статического полиморфизма в C ++?

C ++: Как называется этот метод полиморфизма во время компиляции и каковы его плюсы и минусы?

Стоимость динамических (виртуальных вызовов) по сравнению сстатическая (CRTP) отправка в C ++

0 голосов
/ 18 декабря 2018

Возможно, вы ищете что-то вроде этого:

void somFunc()
{
  std::vector< std::function< bool(bool, bool) > > operators = {
    [](bool a, bool b){ return a && b; },
    [](bool a, bool b){ return a || b; }
  };
  for ( auto& op : operators )
  {
      if ( op( a, b ) )
      {
      }
      else if ( op( a1, b1 ) )
      {
      }
  }
}

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

0 голосов
/ 18 декабря 2018

Вы можете использовать указатели на функции.

#include <iostream>
#include <functional>


bool oper1(bool a, bool b) {
    return a || b;
}


bool oper2(bool a, bool b) {
    return a && b;
}

int main() {
    bool a = true, b = false;
    auto oper = oper1;
    if (oper(a, b)) {
        std::cout << "OR\n";
    }
    oper = oper2;
    if (oper(a, b)) {
        std::cout << "AND\n";
    }
}

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

Вы также можете использовать наследование и функторы:

#include <iostream>
#include <functional>
#include <memory>

class Operator {
public:
    virtual bool eval(bool a, bool b) = 0;
};

class OrOperator : public Operator {
public:
    bool eval(bool a, bool b) {
        return a || b;
    }
};

class AndOperator : public Operator {
public:
    bool eval(bool a, bool b) {
        return a && b;
    }
};

class VariableOperator : public Operator {
public:
    VariableOperator(bool val) : val(val) {}
    bool eval(bool a, bool b) {
        return val;
    }
private:
    bool val;
};

int main() {
    bool a = true, b = false;
    std::unique_ptr<Operator> oper(new OrOperator);
    if (oper->eval(a, b)) {
        std::cout << "OR\n";
    }
    oper.reset(new AndOperator);
    if (oper->eval(a, b)) {
        std::cout << "AND\n";
    }
    oper.reset(new VariableOperator(true));
    if (oper->eval(a, b)) {
        std::cout << "VARIABLE\n";
    }
}
0 голосов
/ 18 декабря 2018

Можно сделать somFunc() шаблоном и принять любую функцию, которая принимает два аргумента и возвращает значение, которое можно протестировать с помощью if.

 #include <functional>    // for binary operations in std

 template<class Operation> void somfunc(Operation oper)
 {
      if (oper(a,b))
      {
            // whatever
      }
 }

 int main()
 {
      somFunc(std::logical_and<int>());
      somFunc(std::logical_or<int>());
      somFunc(std::plus<int>());         //  addition

       //   pass a lambda

      somFunc([](int a, int b) -> int {return a + b;});   // lambda form of addition
 }

В приведенном выше примере I 'мы предположили, что переменные a и b (которые использовались в вопросе, но типы не указаны) имеют тип int.

0 голосов
/ 18 декабря 2018

Не уверен, что это то, что вы просите, но вы можете написать что-то вроде этого:

enum OPERATION { AND, OR }; 

bool operation(bool a, bool b,OPERATION op) {
    if (op == AND) return a && b;
    return a || b;
}    

void somFunc(OPERATION op)
{
    if(operation(a,b,op)) 
    {
    }
}

Или, как предложено в комментарии, сделать операцию, которая будет выполнена, параметром функции,вот так

template <OPERATION> 
void somFunc(OPERATION op)
{
    if(op(a,b)) 
    {
    }
}

и назовите это так

somFunc( [](bool a, bool b) { return a && b; });
somFunc( [](bool a, bool b) { return a || b; });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...