对于使用任意类型的给定参数进行任意操作有什么建议吗?
基本上我只想使用任意类型的给定参数进行任意操作。
参数类型基类是 Var,Operation 是将针对给定参数执行的操作的基类。
我有 Evaluator 类,它包含使用 opId 映射的运算符集合。评估器将根据evaluate()成员函数中给出的opId参数进行操作,然后evaluate()函数将搜索接受参数类型和opId的支持的运算符。
我想问的是,是否有任何有效的模式或算法可以无需dynamic_cast<>来做到这一点?和/或循环操作符集合。
`
class Var {
public:
bool isValidVar();
static Var invalidVar();
}
template<typename T> class VarT : public Var {
public:
virtual const T getValue() const;
}
class Operator {
public:
virtual Var evaluate(const Var& a, const Var& b) = 0;
}
template<typename T> class AddOperator : public Operator {
public:
virtual Var evaluate(const Var& a, const Var& b)
{ //dynamic_cast is slow!
const VarT<T>* varA = dynamic_cast<const VarT<T>*>(&a);
const VarT<T>* varB = dynamic_cast<const VarT<T>*>(&b);
if(varA && varB) //operation supported
{
return VarT<T>(varA->getValue() + varA->getValue());
}
return Var::invalidVar(); //operation for this type is not supported
}
}
class Evaluator {
private:
std::map<int,std::vector<Operator>> operatorMap;
public:
virtual Var evaluate(const Var& a, const Var& b,int opId)
{
std::map<int,std::vector<Operator>>::iterator it = this->operatorMap.find(opId);
if(it != this->operatorMap.end())
{
for(size_t i=0 ; i<it->second.size() ; i++)
{
Var result = it->second.at(i).evaluate(a,b);
if(result.isValidVar())
{
return result;
}
}
}
//no operator mapped, or no operator support the type
return Var::invalidVar();
}
}
`
Basically i just want to do an arbitrary operation using given arguments of arbitrary types.
Argument type base class is Var, and Operation is base class of the operation that will executed for given arguments.
I have Evaluator class, that hold a collection of operators which mapped using opId. Evaluator will do operation based on opId argument given in evaluate() member function, then evaluate() function will do search for supported operator that will accept argument type and opId.
what I want to ask is, is there any efficient pattern or algorithm that will do this without dynamic_cast<> and/or looping through operator collection.
`
class Var {
public:
bool isValidVar();
static Var invalidVar();
}
template<typename T> class VarT : public Var {
public:
virtual const T getValue() const;
}
class Operator {
public:
virtual Var evaluate(const Var& a, const Var& b) = 0;
}
template<typename T> class AddOperator : public Operator {
public:
virtual Var evaluate(const Var& a, const Var& b)
{ //dynamic_cast is slow!
const VarT<T>* varA = dynamic_cast<const VarT<T>*>(&a);
const VarT<T>* varB = dynamic_cast<const VarT<T>*>(&b);
if(varA && varB) //operation supported
{
return VarT<T>(varA->getValue() + varA->getValue());
}
return Var::invalidVar(); //operation for this type is not supported
}
}
class Evaluator {
private:
std::map<int,std::vector<Operator>> operatorMap;
public:
virtual Var evaluate(const Var& a, const Var& b,int opId)
{
std::map<int,std::vector<Operator>>::iterator it = this->operatorMap.find(opId);
if(it != this->operatorMap.end())
{
for(size_t i=0 ; i<it->second.size() ; i++)
{
Var result = it->second.at(i).evaluate(a,b);
if(result.isValidVar())
{
return result;
}
}
}
//no operator mapped, or no operator support the type
return Var::invalidVar();
}
}
`
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您不想使用dynamic_cast,请考虑在您的设计中添加类型特征。
添加 05/03/10 :以下示例将演示运行时特征如何工作
CommonHeader.h
DataProvider 标头
DataProvider 实现
DataConsumer
if you do not want to use dynamic_cast, consider adding type traits into your design.
Added 05/03/10 : The following sample will demonstrate how runtime-traits works
CommonHeader.h
DataProvider header
DataProvider implementation
DataConsumer
如果您可以修改类型
Var
,您可以为参数类型添加 type-Id。但在操作的实现过程中,您总是必须在某些时候使用dynamic_cast
。如果您的类型和操作在编译时是固定的,则可以使用 Boost.MPL(特别是容器)。If you can modify the type
Var
you could add type-Ids for the argument types. But in the implementation of your operations you would always have to use adynamic_cast
at some point. If your types and operations are fixed at compile-time, you can do the whole thing with templates using Boost.MPL (specifically the containers).您的示例代码包含许多错误,包括切片问题。
我不是 100% 确定,但我似乎记得您可以使用
const type_info*
作为地图的键。如果是这样,您可以使用如下所示的内容。它并非不受 RTTI (
type_info
) 的影响,但由于 Evaluator 已经检查了 typeid,因此您可以使用static_cast
而不是dynamic_cast
(但是现在代码不再盲目搜索要应用的正确运算符,这并不重要)。当然,下面在内存管理方面就完全被打破了。使用您选择的智能指针重新实现。
Your sample code contains many errors, including slicing problems.
I'm not 100% sure, but I seem to remember you can use
const type_info*
as a key for a map.If so, you could use something like following. It is not free from RTTI (
type_info
), but since Evaluator already checks the typeids, you can use astatic_cast
instead of adynamic_cast
(but it isn't that important now that the code doesn't blindly search for the right operator to apply).Of course, the following is completely broken in terms of memory management. Reimplement with smart pointers of your choice.