c++和通用图距离算法
C++ and generic graph distance algorithm
我的问题如下。我正在通过编写图形库来学习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
或weighted_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++机制可以从这两个基类中选择"更接近"的基类?
谢谢你的回复,sehe;我找到了问题的最佳解决方案。它是写两个函数,
template <class T>
inline T get_weight(edge const & e)
{ return T(1); }
template <class T>
inline T get_weight(weighted_edge const & e)
{ return T(e.weight); }
这样,当我编写最短路径算法时,它可以请求这两个类中的任何一个的权重或任何派生的,这对我来说很重要,因为我可能想要稍后向基本边缘类添加属性(如颜色等)。因此,当我写
时class my_edge : public edge { ... };
my_edge e;
并使用get_weight(e)
,我将获得未加权边缘的行为。边缘类型的模板在这里没有帮助,因为它不能在edge
之后的所有类上使用规定的行为,并将其与weighted_edge
的行为区分开来。
Up front:我假设您已经考虑过在基础edge
类中使getWeight()
成为虚拟方法(并使默认实现返回1)。我意识到这种方法在灵活性上的局限性,只是想检查一下。
因为我不理解你的返回类型模板的目的,我假设你想推断返回类型,你可以使用我的解决方案。
让get_weight
选择正确实现的通常方法是使用模板专门化(注意,你所展示的代码是根据返回类型专门化的;根据定义,编译器永远不会推导出此类型):
namespace detail
{
template <class Edge> struct get_weight_impl;
template <> struct get_weight_impl<edge>
{
typedef typename result_type int;
result_type operator()(const edge& e) const
{ return result_type(1); }
};
template <> struct get_weight_impl<weighted_edge>
{
typedef typename result_type int;
result_type operator()(const weighted_edge& e) const
{ return result_type(e.weight); }
};
}
Update 1您可以使用
result_of<edge::weight>
(boost/TR1)或decltype(edge::weight)
(c++ 0x)来避免硬编码result_type
类型。这是真正的归纳法。更新2为了使
weighted_edge const&
的重载'service' 派生的边缘类型也应用了一点type_trait的魔力:
http://ideone.com/AqmsL
struct edge {};
struct weighted_edge : edge { virtual double get_weight() const { return 3.14; } };
struct derived_edge : weighted_edge { virtual double get_weight() const { return 42; } };
template <typename E, bool is_weighted>
struct edge_weight_impl;
template <typename E>
struct edge_weight_impl<E, false>
{
typedef int result_type;
int operator()(const E& e) const { return 1; }
};
template <typename E>
struct edge_weight_impl<E, true>
{
// typedef decltype(E().weight()) result_type; // c++0x
typedef double result_type;
result_type operator()(const E& e) const
{
return e.get_weight();
}
};
template <typename E>
typename edge_weight_impl<E, boost::is_base_of<weighted_edge, E>::value>::result_type
get_weight(const E& e)
{
return edge_weight_impl<E, boost::is_base_of<weighted_edge, E>::value>()(e);
}
int main()
{
edge e;
weighted_edge we;
derived_edge de;
std::cout << "--- static polymorphism" << std::endl;
std::cout << "edge:t" << get_weight(e) << std::endl;
std::cout << "weighted_edge:t" << get_weight(we) << std::endl;
std::cout << "derived_edge:t" << get_weight(de) << std::endl;
// use some additional enable_if to get rid of this:
std::cout << "bogus:t" << get_weight("bogus") << std::endl;
std::cout << "n--- runtime polymorphism" << std::endl;
edge* ep = &e;
std::cout << "edge:t" << get_weight(*ep) << std::endl;
weighted_edge* wep = &we;
std::cout << "weighted_edge:t" << get_weight(*wep) << std::endl;
wep = &de;
std::cout << "bogus:t" << get_weight(*wep) << std::endl;
}
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 我是 c++ 的新手,有没有一种算法可以找到 3d 数组中最接近的 0 的距离?
- openCV的EMD-L1算法计算的距离为零
- 有没有一个带有距离标记的最短路径算法的开源实现
- 使用邻接矩阵的 Dijkstra 算法找不到从每个节点到每个其他节点的正确距离/路径
- c++和通用图距离算法
- 基于距离的对象的最快排序算法
- 我如何调整Levenshtein距离算法来限制匹配到单个单词
- 使用正确的优化算法C++在三维空间中查找点之间的距离