5

There are cases where one has pointers in an STL container and where less-than comparison shall not be made by pointer but by the objects pointed to. A simple example would be a vector which shall be sorted by the real numbers. Currently I solve this with:

template<class T_PTR> struct ltDeref
{
    bool operator()(T_PTR p0,T_PTR p1) const {return *p0<*p1;}
};

and use it as

vector<double*> vIn;
sort(vIn.begin(),vIn.end(),ltDeref<double*>());

or

set<double*,ltDeref<double*> > someSet;

Instead of writing my own comparison function, is there a more "standard" way in C++ which doesn't require a user made template?

4

3 回答 3

1

通常,您可以使用可用的functional函子来纯粹从标准构造中构造结果排序函子。

但是没有取消引用指针的方法T*,因此您必须使用自己的比较器。


您可以获得的最接近的是当您的“指针类型”不是原始类型,而是一些operator*可以解决的用户定义类型时。

以下代码是 C++11(使用std::bind起来比std::bind1stand更简单std::bind2nd)。

#include <vector>
#include <algorithm>
#include <functional>
#include <iostream>

// Fakes a "smart pointer" wrapper around data
template <typename T>
struct Ptr
{
    Ptr(T data) : data(data) {};
    const T& operator*() const { return data; }

private:
    T data;
};

int main()
{
    std::vector<Ptr<double>> vIn;
    vIn.push_back(Ptr<double>(5));
    vIn.push_back(Ptr<double>(2));
    vIn.push_back(Ptr<double>(6));

    using namespace std::placeholders;
    std::sort(
        vIn.begin(),
        vIn.end(),
        std::bind(
            std::less<double>(),
            std::bind(&Ptr<double>::operator*, _1),
            std::bind(&Ptr<double>::operator*, _2)
        )
    );

    std::vector<Ptr<double>>::const_iterator it = vIn.begin(), end = vIn.end();
    for ( ; it != end; ++it)
        std::cout << ',' << **it;
}

因此,如果不是double*你有std::unique_ptr<double>or std::shared_ptr<double>,那么这可以工作:

#include <vector>
#include <memory>
#include <algorithm>
#include <functional>
#include <iostream>

int main()
{
    typedef std::unique_ptr<double> STDUPD;

    std::vector<STDUPD> vIn;
    vIn.push_back(STDUPD(new double(5)));
    vIn.push_back(STDUPD(new double(2)));
    vIn.push_back(STDUPD(new double(6)));

    using namespace std::placeholders;
    std::sort(
        vIn.begin(),
        vIn.end(),
        std::bind(
            std::less<double>(),
            std::bind(&STDUPD::operator*, _1),
            std::bind(&STDUPD::operator*, _2)
        )
    );

    std::vector<STDUPD>::const_iterator it = vIn.begin(), end = vIn.end();
    for ( ; it != end; ++it)
        std::cout << ',' << **it;
}

如果可以的话,还有另一个避免“原始”指针的原因......

于 2012-12-30T11:33:47.583 回答
0

正如其他答案所说,没有现成的解决方案。原始指针解引用比较器可以通过使其仅可用于具有以下显式模板特化的原始指针类型来稍微改进。我希望在使用非指针类型的情况下,编译器会给出更好的错误消息。

template<class T>
struct PointeeLess;

template<class T>
struct PointeeLess<T const *>
{
    bool operator()( T const * a , T const * b ) const { return *a < *b; }
};

OTOH,问题中的模板将适用于实现 operator* 的非原始指针类型。

于 2013-04-12T15:29:54.603 回答
0

我在 STL 中寻找同样的东西,但找不到。最后写了我自己的(处理NULL)

class DeRefPtrLess {

public:

template<typename T>
    bool operator()(const T *l, const T *r) const {
        if (l == NULL
                && r == NULL) {
            return false;
        }
        if (l == NULL) {
            return true;
        }

        return *l < *r;
    }

};

于 2020-09-18T17:26:51.610 回答