gpt4 book ai didi

c++ - C++中根据特定类型执行代码

转载 作者:太空狗 更新时间:2023-10-29 21:25:23 27 4
gpt4 key购买 nike

我正在尝试将我以前用函数式语言 (OCaml) 编写的一些代码重写为 C++。

我的问题可以简化为:

  • 我有一堆值(value)观
  • 值可以是变体类型(因此一组不同类型的值,例如 intfloatstd::string, std::list 随便)
  • 我想定义对值起作用的运算符(例如,弹出两个值并将它们的和压入的加法运算)
  • 一些运算符根据在堆栈中找到的类型而表现不同,理想情况下一些运算符甚至根据类型改变参数的数量(一个简单的例子:加法运算符可以弹出一个值,如果它是 std::list 然后将应用的运算符推送到列表的所有值之间,否则弹出另一个值,如果它们都是 float 则进行加法)

到目前为止,我已经能够通过使用模板来使其工作,例如。

class Value
{
public:
Value(Type type) : type(type) { }

virtual string svalue() const = 0;
virtual string lvalue();

virtual bool equals(Value *value) const = 0;
virtual Value* clone() const = 0;

const Type type;

virtual ~Value() { };
}

template <class T>
class TValue : public Value
{
protected:
T value;

public:
TValue(Type type, T value) : Value(type), value(value) {}

void set(T value) { this->value = value; }
T get() const { return this->value; }
};

class Int : public TValue<int>
{
private:

public:
Int(int value) : TValue<int>(TYPE_INT, value) { };

virtual string svalue() const;

virtual bool equals(Value *value) const { return this->value == ((TValue<int>*)value)->get(); }
virtual Value *clone() const { return new Int(value); }
};

然后运算符通过做来解释

Value *v1, *v2,
case OP_PLUS:
{
if (vm->popTwo(&v1, &v2))
{
switch (v1->type << 4 | v2->type)
{
case TYPES(TYPE_INT, TYPE_INT): vm->push(new Int(((Int*)v1)->get() + ((Int*)v2)->get())); break;
case TYPES(TYPE_FLOAT, TYPE_INT): vm->push(new Float(((Float*)v1)->get() + ((Int*)v2)->get())); break;
case TYPES(TYPE_INT, TYPE_FLOAT): vm->push(new Float(((Int*)v1)->get() + ((Float*)v2)->get())); break;
case TYPES(TYPE_FLOAT, TYPE_FLOAT): vm->push(new Float(((Float*)v1)->get() + ((Float*)v2)->get())); break;
}
}
break;
}

现在,这行得通,但我不喜欢这种方法,因为它听起来很笨拙,需要大量类型转换,而且一点也不优雅(与我的功能实现相比)。我开始研究 boost 库,看看是否可以找到更好的方法来管理所有内容,在开始使用它之前,我试图定义一种不同的方式来定义运算符,例如

template <Opcode T, class X, class A>
class Unary
{
public:
static A* ptr(X* x)
{
cout << "Missing instruction!" << endl;
return NULL;
};
};


template <>
class Unary<OP_MINUS, Float, Float>
{
public:
static Float *ptr(Float *x) { return new Float(-x->get()); };
};

这样我就可以做

Float *a = new Float(10);
Float *r = Unary<OP_MINUS, Float, Float>::ptr(f);

这行得通,但我仍然看不出我应该如何以通用方式管理它,以便我可以根据在堆栈中找到的内容和使用的运算符调用正确的函数。

boost 会以某种方式帮助我吗?我想要的是一个类型安全且优雅的解决方案,但 boost 有太多不同的库,我很难理解要寻找什么。如果我遗漏了一些更简单的东西,我不需要使用它,我不认为在为这种任务放弃函数式语言时会遇到这么多困难。

最佳答案

您需要 boost::variant,对于元素列表,boost::make_recursive_variant(因此您可以在类型中引用类型)。

虽然 apply_visitor 允许您将一个函数应用于许多类型,但我发现这样的事情更容易考虑开始(假设您的编译器支持 C++11):

template<typename T, typename Func, typename Types...>
bool TryApplyFuncOn( boost::variant<Types...>& var, Func f ) {
struct HelperVisitor {
HelperVisitor( Func f_ ):func(f_) {}
Func func;
typedef bool return_type;
template<typename U>
return_type operator()( U& unused ) { return false; }
return_type operator()( T& t ) { f(t); return true; }
};
return boost::apply_visitor( HelperVisitor(f), var );
}

它接受一个你想应用函数的类型和一个变体,并应用它,当且仅当你要求应用的类型是变体中的类型。如果找到匹配项,它会返回 true。

一般情况下,您可以“一次完成”。

所以你可以这样做:

// easy case:
typedef boost::variant<int,double> scalar;
scalar times_two(scalar const& left) {
scalar retval = left;
TryApplyFuncOn<int>( retval, []( int& value ){ value*=2; } );
TryApplyFuncOn<double>( retval, []( double& value ){ value*=2.; } );
return retval;
}
// tricky case:
scalar multiply(scalar const& left, scalar const& right) {
scalar retval = left;
TryApplyFuncOn<int>( retval, [&right]( int& left_value ){
TryApplyFuncOn<int>( right, [&left_value]( int& right_value ){
left_value *= right_value;
});
TryApplyFuncOn<double>( right, [&left_value]( double& right_value ){
left_value *= right_value;
});
});
TryApplyFuncOn<double>( retval, [&right]( double& left_value ){
TryApplyFuncOn<int>( right, [&left_value]( int& right_value ){
left_value *= right_value;
});
TryApplyFuncOn<double>( right, [&left_value]( double& right_value ){
left_value *= right_value;
});
});
return retval;
}

它还没有进行类型 boost (所以 int*double 不会变成 double),但是没有任何基本的东西可以阻止它。

有道理吗?

关于c++ - C++中根据特定类型执行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14083633/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com