具有自定义参数的比较器功能的模板

时间:2014-03-28 02:26:37

标签: c++ templates c++11 types

我正在研究数据结构,我希望它具有比较功能,可以传递给构造函数,与stl数据结构(set,queue等)的工作方式相同。我还想要一个构造函数中提供的默认函数。

问题是,对结构的查询是一个函数模板,它将自定义类型作为参数。但如果我不知道查询的类型,我也不知道如何提供默认的比较功能。有没有办法做到这一点?

如果Query与NodeType相同(在此示例中查询无用),则此方法有效:

template<class NodeType, class Query = NodeType>
inline float eucDistance(const Query * p1, const NodeType * p2) {
    ...
}


template<class NodeType, typename Comp = decltype(eucDistance<NodeType>)>
class KDTree {

    Comp* distance;

public:

    KDTree(Comp comaprator = &eucDistance<NodeType>) : distance(comaprator) {

    }

    template<class Query = NodeType>
    NodeType * nearestNeighbor(const Query *query) {
        ...
        float tmp = distance(query, sth); 
        //I want something like distance<NodeType, Query>(query, sth); 
        ...
   }
}

但我想做这样的事情:

class Point; //some type that the tree contains

KDTree<Point> tree;
Point p1;
Point *p = tree.nearestNeighbor(&p1); //this works with the given example
...
vec3 vec = ...; //some different type as a query
p = tree.nearestNeighbor<vec3>(vec); // <-- this is what I would like to do

2 个答案:

答案 0 :(得分:1)

template<typename Query, typename NodeType = Query>
inline float eucDistance(const Query * p1, const NodeType * p2) {
    ...
}

class KDTree {
public:
    template<typename Query = NodeType, typename Comparator>
    NodeType * nearestNeighbor(const Query *query, Comparator comp) {
        ...
        float tmp = comp(query, sth);
        ...
   }
}

此代码接收成员函数级别的比较器,因此它可以采用不同类型的节点。模板类型扣除也会起作用;所以不要像comp<T>(a, b);那样调用函数,而只需comp(a, b)就可以了。

你的代码和C ++标准库函数(算法)之间的主要区别在于它们不会强制它们成为指针,而是强制指向函数的C风格指针。相反,他们使用functors

std::for_each调用传递的元素的仿函数;因此需要一个仿函数

template <typename InputIter, typename UnaryFunc>
UnaryFunc std::for_each(InputIter first, InputIter last, UnaryFunc func)
{
    for (; first != last; ++first)
        func(*first);
    return func;
}

如果你注意到,那就没有指针了。它使用运算符func调用();它的优点在于它既适用于C风格的函数指针,也适用于C ++风格的仿函数,即定义了struct的{​​{1}}。另请注意,用于函子的模板类型与函子接受的类型无关。

答案 1 :(得分:0)

您应该使用多态仿函数而不是普通函数,例如

struct eucDistance
{
    float operator()(Point, Point) const;
    float operator()(vec3, Point) const;
    ...
};
顺便说一下,你真的应该看一下Boost.Geometry并设计R-tree