在C ++中运行时更改操作

时间:2018-12-18 09:10:42

标签: c++ templates

我手头有一个小问题。假设有一个只有2个操作数的if条件,但我想使操作动态化。

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 / else中有n个if条件。如果我以某种方式实现了这一目标,我将条件减少了一半。

5 个答案:

答案 0 :(得分:4)

不确定这是否是您要的内容,但是您可以编写如下内容:

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; });

答案 1 :(得分:1)

您可以使用指向功能的指针。

#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";
    }
}

答案 2 :(得分:1)

您可能正在寻找这样的东西:

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 ) )
      {
      }
  }
}

您可以添加更多运算符或足够容易地更改参数类型。

答案 3 :(得分:1)

您也可以通过 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);
}

请参见 live example here

相对于虚拟继承 CRTP 有什么优势? CRTP是静态多态性的一种情况。这里是一些参考:

Compile time vs run time polymorphism in C++ advantages/disadvantages

What is the motivation behind static polymorphism in C++?

C++: How is this technique of compile-time polymorphism called and what are the pros and cons?

The cost of dynamic (virtual calls) vs. static (CRTP) dispatch in C++

答案 4 :(得分:0)

可以将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
 }

在上面,我假设变量ab(已在问题中使用,但类型未指定)的类型为int