C++与通用图距离算法

C++与通用图距离算法,c++,templates,graph,boost-graph,C++,Templates,Graph,Boost Graph,我的问题如下。我通过编写图形库来学习C++,并希望尽可能多地使用泛型编程技术;因此,通过使用BOOST回答我的问题对我没有帮助;事实上,我试图通过BOOST的代码寻找我问题的答案,但这是一次令人谦卑的经历,因为我甚至不知道某些函数是在哪里定义的;只是在我的水平上学习C++的水平太高了。 也就是说,我的库以以下方式模板化: class edge { ... }; template <class edge_T> class node { ... }; template <cla

我的问题如下。我通过编写图形库来学习C++,并希望尽可能多地使用泛型编程技术;因此,通过使用BOOST回答我的问题对我没有帮助;事实上,我试图通过BOOST的代码寻找我问题的答案,但这是一次令人谦卑的经历,因为我甚至不知道某些函数是在哪里定义的;只是在我的水平上学习C++的水平太高了。 也就是说,我的库以以下方式模板化:

class edge { ... };

template <class edge_T>
class node { ... };

template <class edge_T, class node_T>
class graph { ... };
这并不完全是用户友好的,或者至少是令人困惑的,因为您不希望涉及任何权重

BGL使用get函数获取权重;我可以编写一个返回1或权重的函数,这取决于边,但我关心的是当一个函数从边或加权边派生时会发生什么?如果有人写道:

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++机制可以从这两个基类中选择“更接近”的基类?

UpFord:假设你已经考虑让GeFug在BuffEdge类中成为一个虚拟方法,并使默认实现返回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); }
    };
}

谢谢你的回复,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); }

使用get_weight,我将获得未加权边的行为。在边缘类型上进行模板化在这里没有帮助,因为它无法在从边缘开始的所有类上使用规定的行为,并将其与加权边缘的行为区分开来。

+1如果您提供了一个最小的工作示例,人们可以使用您要求的功能进行扩展。一般来说,制作一个提升图来识别你的结构是一个适应和添加特征的问题,但是我们不能展示如何识别,除非我们看到其中的内容。你是在尝试使用还是在试图避免使用BGL?我认为这个问题已经很好地解决了,代码从编码的角度解释了一切。无论如何,我试图避免使用BGL-我提到它是我试图学习的东西,但失败得很惨:。我对这个解决方案有点困惑,因为您使用的是边缘类型的模板。无论如何,我发现解决我的特定问题的最佳解决方案确实是我在原始帖子中写的,一个以返回类型为模板并针对不同边缘类型重载的函数。因为我不理解返回类型模板的用途,我假设您想要推导出返回类型,您可以使用我的解决方案来实现。我更新了我的答案,展示了如何使用type_traits来接受加权_edge的任何派生类,很高兴您找到了一个可行的解决方案,也很简单!我猜我之所以复杂的要求是因为你的“模板返回型”实际上不做任何事情:它只是一种奇怪的方式来写一个GETHYBUTE,与双GueGueTeTi正从硬C C移动到C++完全一样。所以我想这更接近我通常的T.e:。在T上模板化的原因是,未加权的情况很可能希望使用整数类型来计算路径成本,因此有必要在T上模板化,而不是简单地在任何地方使用double/float。
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); }
    };
}
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;
}
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;