1

さまざまなタイプの約 30 のメンバーを持つ POD があり、数千の POD をコンテナーに格納し、そのコンテナーをそれらのメンバーの 1 つで並べ替えたいと考えています。

例えば:

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

Person並べ替えたい何千ものオブジェクト、idNumberまたは並べ替えるために選択した他のメンバー。

私は今日これをしばらく研究してきましたが、これに対する最も効率的な、または少なくとも最も単純な解決策は、まったく使用structしないことであり、使用するtupleためにカスタム比較ファンクターにインデックス番号を渡すことができる方法です。でstd::sort(このページの例は、このタイプのソートを簡単に実装する 1 つの方法を示していますが、a の 1 つのメンバーに対して行うstructと、テンプレートを作成するのはそれほど簡単ではなくなります。tuple提供します。)

このアプローチに関する私の 2 つの部分からなる質問は、1) 数十のメンバーを持つタプルがかなり大きくなることは許容されますか? structそして2)これの代わりに使い続けるための同様にエレガントな解決策はありtupleますか?

4

4 に答える 4

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には、カスタム コンパレータを使用して、大なり比較や​​その他の比較を行うことができます。

于 2013-05-21T07:49:50.483 に答える
3

1) タプルがかなり大きく、数十のメンバーを持つことは許容されますか?

はい、許容されます。ただし、操作する必要があるのはタプル内のインデックスだけであるため、維持するのは簡単ではありません。これはマジック ナンバーに非常に似ています。あなたが得ることができる最善の方法は、enum保守が困難な を使用して名前からインデックスへのマッピングを再導入することです。

2)これにタプルの代わりに構造体を使用し続けるための同様にエレガントなソリューションはありますか?

特定の構造体メンバーにアクセスするためのテンプレート関数を簡単に作成できます (公平を期すために、私はあまり力を入れていませんでした。これは何よりも概念実証であるため、どのように実行できるかがわかります)。

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;
}

そこから、余暇に使用できる一般的なコンパレーターを作成するのも同じくらい簡単です (演習としてお任せします)。この方法では、メンバーを名前で参照できますが、メンバーごとに個別のコンパレーターを記述する必要はありません。

于 2013-05-21T07:47:10.063 に答える
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を見たいと思うかもしれません。

于 2013-05-21T07:51:56.303 に答える