结构上的ORDER BY的C++实现

bli*_*ard 9 c++ sorting boost stl compare

我在这里和其他网站上搜索了很多,但我还没有找到令人满意的东西.

我需要的是一个非常简单的任务 - 基本上在c ++中构造ORDER BY运算符.这意味着我有多个不同数据类型成员的结构,我需要一个比较器,成员和订单可配置.这是我的伪代码想法:

comparator.add(&MyStruct::member1, std::less);
comparator.add(&MyStruct::member2, std::greater);
std::sort(my_vector.begin(), my_vector.end(), comparator);
Run Code Online (Sandbox Code Playgroud)

我得到按member1排序的数据,如果它等于member2决定,依此类推.

我在stl和模板方面不太好,但我可以阅读并破译一些代码并发现这是非常合适的解决方案:https://stackoverflow.com/a/11167563

不幸的是,在我的工作中,我必须使用带有错误的32位编译器的c ++ builder,拒绝编译这个正确的代码.它确实 支持c ++ 11几乎没有任何东西,它可以提升1.39.

有没有人可以使用我的资源为我提供任何解决方案?先感谢您

编辑:

我得到了非常专业的解决方案,其中包含我所知道的难以编写的比较运算符,而且这些运算符在这里不起作用.我在我的问题中错过了这个.我的结构至少有15个成员,正如我所写,我需要经常更改成员/列的单独排序方向(asc,desc).我也需要经常更改已排序成员的集合,就像在sql中按运算符顺序一样.我也不能使用类似stable_sort的东西,因为我只是为某些类的OnCompare事件编写比较器.

Jam*_*nze 4

这并不太难。首先,考虑“规范”的排序关系:

struct Compare
{
    bool operator()( C const& lhs, C const& rhs ) const
    {
        return lhs.a < rhs.a
            || ( !(rhs.a < lhs.a) && lsh.b < rhs.b )
            || ( !(rhs.a < lhs.a) && !(rhs.b < lhs.b) && lhs.c < rhs .c )
            || ...
    }
};
Run Code Online (Sandbox Code Playgroud)

显然,没有人会真正写出这样的东西,但它完全符合所需内容的正式定义。

当然,如果我们可以将数据成员想象为一个数组,我们可以将其重写为循环,利用之前!(rhs[i-1] < lsh[i-1]在每种情况下建立的:

struct Compare
{
    bool operator()( C const& lhs, C const& rhs ) const
    {
        int i = 0;
        while ( i != N && !(lhs[i] < rhs[i]) && !(rhs[i] < lhs[i]) ) {
            ++ i;
        }
        return i != N && lhs[i] < rhs[i];
    }
};
Run Code Online (Sandbox Code Playgroud)

或者,如果所有元素都是全序的,那么==也定义了它们,我们可以假设它对应于弱偏序建立的等价关系:

struct Compare
{
    bool operator()( C const& lhs, C const& rhs ) const
    {
        int i = 0;
        while ( i != N && !(lhs[i] == rhs[i]) ) {
            ++ i;
        }
        return i != N && lhs[i] < rhs[i];
    }
};
Run Code Online (Sandbox Code Playgroud)

剩下的就是以某种方式将其转换为可以处理任意类型元素的任意顺序的东西。有句老话说,每个问题的解决方案都是额外的间接级别,这句话也适用于此。

首先,我们需要一些方法来处理每个元素的不同类型。多态性似乎是合适的(尽管如果元素评估的顺序在编译时固定,模板也可以工作):

struct CompareOneElementOfC
{
    virtual bool isLessThan( C const& lhs, C const& rhs) const = 0;
    virtual bool isEqual( C const& lhs, C const& rhs) const = 0;
};

template <typename T, T C::*ptr>
struct ConcreteCompareOneElementOfC : public CompareOneElementOfC
{
    virtual bool isLessThan( C const& lhs, C const& rhs) const
    {
        return lhs.*ptr < rhs.*ptr;
    }
    virtual bool isEqual( C const& lhs, C const& rhs) const
    {
        return lhs.*ptr == rhs.*ptr;
    }
};
Run Code Online (Sandbox Code Playgroud)

根据元素的类型,您可能需要手动编写特定的具体实例。如果任何元素不支持全排序,则必须省略 isEqual, 并相应地修改以下代码。

到目前为止,我们只需要每个具体 Compare 的一个静态实例:

ConcreteCompareOneElementOfC<int, &C::a> const c1;
ConcreteCompareOneElementOfC<double, &C::b> const c2;
//  ...
Run Code Online (Sandbox Code Playgroud)

最后,将这些实例的地址放入一个表中:

CompareOneElementOfC const* const cmp[] = { &c1, &c2 ... };
Run Code Online (Sandbox Code Playgroud)

您可以为不同的订单使用不同的表。如果只有几个,请为每个定义静态表,然后使用它。如果顺序可以是任意的,请在每次排序之前按照所需的顺序动态创建表。

最后:

class Compare
{
    CompareOneElementOfC const* const* begin;
    CompareOneElementOfC const* const* end;
public:
    template< size_t N >
    Compare( CompareOneElementOfC const* const (&cmp)[N] )
        : begin( cmp )
        , end( cmp + N )
    {
    }
    bool
    operator()( C const& lhs, C const& rhs ) const
    {
        auto current = begin;
        while ( current != end && (*current)->isEqual( lhs, rhs ) ) {
            ++ current;
        }
        return current != end && (*current)->isLessThan( lhs, rhs );
    }
}
Run Code Online (Sandbox Code Playgroud)

(请注意,我还没有实际测试过这段代码,因此可能存在拼写错误和其他错误。不过,基本思想应该是存在的。)