大POD作为排序的元组

时间:2013-05-21 07:28:27

标签: c++ sorting struct tuples containers

我有一个POD,有大约30个不同类型的成员,我想要将数千个POD存储在一个容器中,然后由其中一个成员对该容器进行排序。

例如:

 struct Person{
   int idNumber;
   ....many other members
 }

我希望按Person或我选择排序的任何其他成员排序的数千个idNumber个对象。

我今天已经研究了一段时间了,似乎最有效,或者至少是最简单的解决方案就是根本不使用struct,而是使用tuple我可以将索引号传递给自定义比较函数,以便在std::sort中使用。 (this page上的示例显示了一种轻松实现此类排序的方法,但是对struct的单个成员执行此操作会使得模板化不那么容易,因为您必须通过以下方式引用成员:名称,而不是tuple提供的索引。)

关于这种方法我的两部分问题是:1)一个元组是否可以接受相当大,有几十个成员? 2)是否有同样优雅的解决方案继续使用struct代替tuple

4 个答案:

答案 0 :(得分:6)

您可以制作一个比较器,用于存储指向成员的指针,以便它知道要进行比较的成员:

struct POD {
    int i;
    char c;
    float f;
    long l;
    double d;
    short s;
};

template<typename C, typename T>
struct Comp {

    explicit Comp(T C::* p) : ptr(p) {}

    bool operator()(const POD& p1, const POD& p2) const
    {
        return p1.*ptr < p2.*ptr;
    }

private:
    T C::* ptr;
};

// helper function to make a comparator easily

template<typename C, typename T>
Comp<C,T> make_comp( T C::* p)
{
    return Comp<C,T>(p);
}

int main()
{
    std::vector<POD> v;
    std::sort(v.begin(), v.end(), make_comp(&POD::i));
    std::sort(v.begin(), v.end(), make_comp(&POD::d));
    // etc...
}

为了进一步概括这一点,让make_comp采用自定义比较器,这样你就可以进行大于和等比较。

答案 1 :(得分:3)

  

1)元组是否可以接受相当大,有几十个成员?

是的,这是可以接受的。然而,它将不容易维护,因为您必须使用的是元组内的索引,这非常类似于幻数。您可以获得的最好效果是使用enum重新引入名称到索引的映射,这也难以维护。

  

2)是否有一个同样优雅的解决方案继续使用struct而不是元组?

您可以轻松编写模板函数来访问特定的结构成员(公平地说,我没有付出太多努力,它更像是一个概念证明而不是其他任何东西,因此您可以了解它是如何形成的完成):

template<typename T, typename R, R T::* M>
R get_member(T& o) {
  return o.*M;
}

struct Foo {
  int i;
  bool j;
  float k;
};

int main() {
  Foo f = { 3, true, 3.14 };
  std::cout << get_member<Foo, float, &Foo::k>(f) << std::endl;
  return 0;
}

从那里开始,编写一个可以随意使用的通用比较器同样容易(我会把它作为练习留给你)。这样你仍然可以通过名字引用你的成员,但你不需要为每个成员编写一个单独的比较器。

答案 2 :(得分:1)

您可以使用模板提取排序键:

struct A
{
    std::string name;
    int a, b;
};

template<class Struct, typename T, T Struct::*Member>
struct compare_member
{
    bool operator()(const Struct& lh, const Struct& rh)
    {
        return lh.*Member < rh.*Member;
    }

};

int main()
{
    std::vector<A> values;
    std::sort(begin(values), end(values), compare_member<A, int, &A::a>());
}

如果你想用不同的键索引(排序)对象,也许你想看看boost::multi_index_container这是一个非常强大的容器。

答案 3 :(得分:0)

创建一个类,该类可以使用指向Person成员数据的指针进行比较:

 std::sort(container.begin(), container.end(), Compare(&Person::idNumber));

Compare的位置:

template<typename PointerToMemberData>
struct Compare {
     Compare(PointerToMemberData pointerToMemberData) :
     pointerToMemberData(pointerToMemberData) {
     }

     template<typename Type
     bool operator()(Type lhs, Type rhs) {
         return lhs.*pointerToMemberData < rhs.*pointerToMemberData
     }

     PointerToMemberData pointerToMemberData;
};