C++和通用图距离算法
我的问题如下。我正在通过编写图形库来学习 C++,并希望尽可能多地利用通用编程技术;因此,通过“使用 BOOST”回答我的问题对我没有帮助;事实上,我尝试通过 BOOST 的代码来寻找我的问题的答案,但这是一次令人羞愧的经历,因为我什至无法弄清楚某些函数是在哪里定义的;以我的水平来说,C++ 的水平太高了。
也就是说,我的库是通过以下方式进行模板化的:
class edge { ... };
template <class edge_T>
class node { ... };
template <class edge_T, class node_T>
class graph { ... };
并且我通过使用从边或节点派生的类来创建更复杂的图,因此加权边类将很简单
template <class T>
class weighted_edge : public edge {
public:
T weight;
...
};
现在的问题是我想在此结构上实现一个算法计算两个顶点之间的最短距离。我可以轻松地编写其中两个,一个用于加权边缘,一个用于未加权,但变化很小:一个将访问 weighted_edge
(或派生类)的成员字段,另一个将假设单一权重。
有没有办法做到这一点,以便我可以只用一段代码来处理这两种情况?
一种解决方案是使用成员函数 edge::get_weight()
,该函数将返回权重(或在未加权的情况下返回“1”),但这将迫使我为边类使用特定的权重类型这是未加权的,所以闻起来很有趣。我的意思是,模板需要
template <class T>
class edge {
public:
...
virtual T get_weight(void) { return T(1); }
}
不完全用户友好,或者至少令人困惑,因为您不希望涉及任何权重。
BGL使用get()
函数来获取权重;我可以编写一个根据 edge_T
返回 1 或 weight
的函数,但我担心的是当从 edge
或 派生时会发生什么代码>加权边缘?如果有人写道:
template <class T>
inline T get_weight(edge & e) { return T(1); }
template <class T>
inline T get_weight(weighted_edge & e) { return T(e.weight); }
如果传递一个派生类会发生什么?是否有一种 C++ 机制可以从这两个基类中选择“更接近”的基类?
My problem is the following. I am learning C++ by writing a graph library and want to make use of as much generic programming techniques as possible; hence, answering my question through "use BOOST" will not help me; in fact, I tried looking through BOOST's code for an answer to my question, but it was a humbling experience, since I can't even figure out where certain functions are defined; just way too high level of C++ for learning from it at my level.
That said, my library is templated in the following way:
class edge { ... };
template <class edge_T>
class node { ... };
template <class edge_T, class node_T>
class graph { ... };
and I am creating more complex graphs by using classes derived from edge or node, so a weighted edge class would be simply
template <class T>
class weighted_edge : public edge {
public:
T weight;
...
};
The problem now is that I want to implement an algorithm on this structure that computes the shortest distance between two vertices. I could easily write two of these, one for weighted edges and one for unweighted, but the change is tiny: one would access a member field of weighted_edge
(or derived classes) and the other would assume unitary weight.
Is there a way of doing this, so that I can have just one piece of code for both cases?
One solution is to use a member function edge::get_weight()
that would return the weight (or '1' in unweighted case), but that would force me to use a specific weight type for edge class that is unweighted, so it smells funny. I mean, the template would need to be
template <class T>
class edge {
public:
...
virtual T get_weight(void) { return T(1); }
}
which is not exactly user-friendly, or at least confusing, since you don't expect that there should be any weights involved.
BGL uses a get()
function to obtain the weight; I could write a function that returns 1 or the weight
depending on the edge_T
, but my concern is what happens when one derives from edge
or weighted_edge
? If one writes:
template <class T>
inline T get_weight(edge & e) { return T(1); }
template <class T>
inline T get_weight(weighted_edge & e) { return T(e.weight); }
what would happen if one passed a derived class? Is there a C++ mechanism that would select the 'closer' base class out of these two?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
谢谢您的回复,呵呵;我找到了解决我的问题的最佳解决方案。就是编写两个函数,
这样,当我编写最短路径算法时,它可以要求这两个类或任何派生类的权重,这对我来说很重要,因为我可能稍后想要向基本边缘类添加属性(如颜色等)。因此,当我编写
和使用 get_weight(e) 时,我将获得未加权边缘的行为。边缘类型上的模板在这里没有帮助,因为它无法在从
edge
派生的所有类上使用规定的行为,并将其与weighted_edge
的行为区分开来。Thanks for the response, sehe; I figured out the optimal solution for my problem. It is to write two functions,
This way, when I write a shortest-path algorithm it can ask for the weight of either of these two classes or any derived ones, which is important to me because I might want to add properties to the base edge classes later on (like colors, etc.). Hence, when I write
and use
get_weight(e)
I will get the behavior for the unweighted edge. Templating on the edge type would not help here, because it would not be able to use the prescribed behavior on all classes descending fromedge
, and distinguishing that from the behavior forweighted_edge
.前面:我假设您已经考虑过将
getWeight()
设为基edge
类中的虚拟方法(并将默认设置为执行返回1)。我知道这种方法的灵活性有限,只是想检查一下。因为我不明白您的返回类型模板的目的,所以我假设您想要推断返回类型,您可以使用我的解决方案来做到这一点。
让
get_weight
选择正确实现的常用方法是使用模板特化(请注意,您显示的代码通过返回类型进行特化;根据定义,编译器永远不会推导出这种类型):>http://ideone.com/AqmsL
Up front: I assume you have thought of making
getWeight()
a virtual method in the baseedge
class (and make the default implementation return 1). I'm aware of the limitations in flexibility of this approach, just wanted to check.Because I didn't understand the purpose of your return type templae, I assumed that you wanted to deduce the return type, which you can do using my solution.
The usual way to make
get_weight
select the right implementation is to use template specialization (note that the code you show specializes by return type; by definition this type would never be deduced by the compiler):http://ideone.com/AqmsL