用于访问作为参数传递的对象的不同成员的模板
我有一个函数来计算在相邻点集上定义的不同变量的梯度。算法总是相同的,但根据计算的内容,访问邻居的不同成员数据,例如,在计算速度梯度时,使用Node::velocity
,计算应力梯度时,使用Node::stress
。避免多次编写相同函数的最佳方法是什么?
我想到了几种可能性:
传递 lambda 函数 (c++0x) 或返回相关特定成员数据的可调用对象,称为
gradVelocity=computeGradient(listOfNeighbors,[](const Node& n){ return n.velocity; });
减号是每次读取时的额外函数调用。
根据整数来模板化函数,说明正在计算的内容:
enum{VAL_VELOCITY=0,VAL_STRESS,VAL_SOMETHING}; 模板
computeGradient(const std::list<节点>& 邻居){ /*循环邻居*/ value=(what==VAL_VELOCITY?neighbor.velocity:((what==VAL_STRESS)?neighbor.stress:neighbor.something); /* 等等 */ } /* 这样调用 */ gradVelocity=computeGradient (邻居); 它也许应该是高效的(希望编译器能够在各个实例化中使用常量来优化条件),但可读性和可维护性相当低。
有更好的主意吗?
I have a function to compute gradient of different variable defined on set of neighbor points. The algorithm is always the same, but depending on what is computed, different member data of the neighbors are accessed, e.g. when computing gradient of velocity, use Node::velocity
, when computing gradient of stress, use Node::stress
. What is the best way to avoid writing the same function several times?
I had several possibilities in mind:
Pass lambda function (c++0x)
or callable object returning that particular member data in question, called likegradVelocity=computeGradient(listOfNeighbors,[](const Node& n){ return n.velocity; });
The minus is extra function call at every read.
Template the function based on integer saying what is being computed:
enum{VAL_VELOCITY=0,VAL_STRESS,VAL_SOMETHING}; template<int what> computeGradient(const std::list<Node>& neighbors){ /*loop over neighbors*/ value=(what==VAL_VELOCITY?neighbor.velocity:((what==VAL_STRESS)?neighbor.stress:neighbor.something); /* and so on */ } /* called like this */ gradVelocity=computeGradient<VAL_VELOCITY>(neighbors);
It should be perhaps efficient (hoping compiler will optimize the conditional with constants away in individual instantiations), but readability and maintainability is pretty low.
Some better idea?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果所有字段都具有相同的类型,则很容易使用指向成员的指针:
更新:如果不是,则仍然很容易将指向成员的指针与模板结合起来:
我认为这可能是最有效的方法方式。也是相当的形象生动。
If all of your fields have the same types, it's easy to use pointers to members:
Update: If not, it's still easy to combine pointers to members with templates:
I think this is probably the most efficient possible way. It's pretty vivid too.
指向成员的指针就是您所需要的。类型写为
TS::*
T 是数据成员的类型,S 是结构或类。这是一个小例子:Pointer to member is what you need. The type is written as
T S::*
T is the type of the data member, S is your struct or class. Here is a small example:我是 Boost.Fusion 的忠实粉丝,更具体地说,是 Boost.Fusion.Map,它可以让你构建一个类型 ->值类型的地图。
现在,您可以使用 types 访问地图:
返回对
boost::fusion::result_of::at_key::type
类型变量的引用通过适当的包装,您将获得:
当然,由于我们正在谈论模板,因此根本没有运行时损失:)
I am a huge fan of Boost.Fusion, and more specifically, the Boost.Fusion.Map, which let you build a type -> value kind of map.
Now, you can access the map with types:
returns a reference to a variable of type
boost::fusion::result_of::at_key<Velocity, Map>::type
With appropriate wrapping, you get:
And of course, since we are talking templates, no runtime penalty, at all :)
从
Node
继承并使用虚拟访问怎么样?甚至可以使用 CRTP 来避免虚拟呼叫。What about inheriting from
Node
and using virtual access? It would even be possible to use CRTP to avoid the virtual call.您可以将
velocity
、stress
、something
组合在一个数组中,并根据enum
索引访问它们。用法:
[注意:如果您想将
属性
保留在私有
区域内,则在Node
中提供getter和setter方法来访问它们。]You can combine
velocity
,stress
,something
in a single array and access them based onenum
index.Usage:
[Note: If you want to keep
attributes
insideprivate
region then provide getter and setter methods inNode
for accessing them.]