read-eval-print loop

プログラミング関連のメモ

メンバー関数にもとづいてソートする

「オブジェクトの状態に依存したソートを行いたい」ということがあると思います。

#include <vector>

using namespace std;

class A {
public:
  A(int k);
  vector<int> sorted();
private:
  vector<int> vec;
  int param;
};

A::A(int k) {
  param = k;
}

vector<int> A::sorted() {
  // paramに依存したソートをして返す
}

そこでメンバー関数をsortの比較関数に使う方法として

  1. bind関数を使う方法
  2. 関数オブジェクトを定義する方法

の2つを紹介したいと思います。 (後続のコードのうち既出のコードと重複する部分を適宜省略します。)

1. bind関数を使う方法 (C++11以降)

#include <function> // bind

using namespace std::placeholders;

class A {
private:
  bool cmp(int a, int b);
}

vector<int> A::sorted() {
  vector<int> ret = vec;
  sort(ret.begin(),ret.end(),bind(&A::cmp,this,_1,_2));
  return ret;
}

bool A::cmp(int a, int b) {
  return a%param < b%param;
}

考えてみればparambindを使って渡せるのでcmpが2引数である必要もないですね。

2.関数オブジェクトを明示的に定義する方法

比較のためのクラスcmpを定義し、関数呼び出し演算子()オーバーロードします。

class A {
private:
  class cmp {
  public:
    A &a;
    cmp(A &a) : a(a) {};
    bool operator() (int x, int y) {
      return x%a.param < y%a.param;
    };
  };
};

vector<int> A::sorted() {
  vector<int> ret = vec;
  sort(ret.begin(),ret.end(),cmp(*this));
  return ret;
}

とくに前者のような関数型のアプローチは適用範囲が広そうなので、覚えておいて損はないと思います。