我手头有一个小问题。假设有一个只有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条件。如果我以某种方式实现了这一目标,我将条件减少了一半。
答案 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);
}
相对于虚拟继承, 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
}
在上面,我假设变量a
和b
(已在问题中使用,但类型未指定)的类型为int
。