2013年7月13日土曜日

[C++]メンバ変数を比較してソート

テンプレートを使う練習をかねて、構造体のメンバ変数同士を比較してソートしてみます。

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <string>

using namespace std;

/* メンバ変数同士を比較するためのクラス */
template <typename T, typename Elem>
class MemberComp {
private:
  Elem T::* e;

public:
  MemberComp(Elem T::* e) {
    this->e = e;
  };

  bool operator()(const T &a, const T&b) {
    return a.*e < b.*e;
  };
};

template <typename T, typename Elem, typename Nest>
class NestedMemberComp {
private:
  Nest T::* nest;
  Elem Nest::* e;

public:
  NestedMemberComp(Nest T::* nest, Elem Nest::* e) {
    this->nest = nest;
    this->e = e;
  };

  bool operator()(const T &a, const T&b) {
    return a.*nest.*e < b.*nest.*e;
  };
};

/* インスタンス作成時に型名を省略するための関数 */
template<typename T, typename Elem>
MemberComp<T, Elem> make_comp(Elem T::* e) {
  return MemberComp<T, Elem>(e);
}

template<typename T, typename Elem, typename Nest>
NestedMemberComp<T, Elem, Nest> make_comp(Nest T::* nest, Elem Nest::* e) {
  return NestedMemberComp<T, Elem, Nest>(nest, e);
}

/* 比較対象の構造体 */
struct Data {
  int a;
  double b;
  struct _c {
    int d;
  } c;
};

void print_data(Data *t, int n) {
  for (int i = 0; i < n; ++i) {
    cout << t[i].a << ", "
         << setprecision(2) << setiosflags(ios::fixed) << t[i].b 
         << ", " << t[i].c.d << endl;
  }
}

int main(void) {
  Data target[3] = {{0, 1.5, {3}},
                    {1, 3.0, {2}},
                    {2, 2.0, {1}}};

  print_data(target, 3);

  cout << "b でソート" << endl;
  std::sort(target, target + 3, make_comp(&Data::b));
  print_data(target, 3);

  cout << "c.d でソート" << endl;
  std::sort(target, target + 3, make_comp(&Data::c, &Data::_c::d));
  print_data(target, 3);

  // lambda式を使える場合
  cout << "lambda式を使って b でソート" << endl;
  std::sort(target, target + 3, [](const Data &a, const Data &b) { return a.b < b.b; });
  print_data(target, 3);

  return 0;
}

実行結果

0, 1.50, 3
1, 3.00, 2
2, 2.00, 1
b でソート
0, 1.50, 3
2, 2.00, 1
1, 3.00, 2
c.d でソート
2, 2.00, 1
1, 3.00, 2
0, 1.50, 3
lambda式を使って b でソート
0, 1.50, 3
2, 2.00, 1
1, 3.00, 2

lambda式を使えると楽で良さそう。C++11を使えればなぁ。

0 件のコメント:

コメントを投稿