ページ 11

listでのクラスのメンバ変数のソート

Posted: 2010年11月15日(月) 21:52
by bbcs
どうも。毎回STLについて質問させていただいてます
今回もSTLについてです。


STLのlistにおいて、クラスのメンバ変数についてソートしたいのですが
調べてみてもよく分かりません・・・
演算子のオーバーロードが必要とか何とかで全く分かりません
2つほど質問があるので、回答をお願いします

質問1
class A
{
public:
int a;
A(int _a){a = _a}
}

というクラスがあるとして、クラスAのメンバ変数aについてソートする方法を教えてください。

質問2
今回の質問に関して別の話としてですが、
演算子のオーバーロードをする必要性と
演算子のオーバーロードをすることのメリットを教えてください

よろしくお願いします

Re:listでのクラスのメンバ変数のソート

Posted: 2010年11月16日(火) 01:02
by めるぽん
>クラスAのメンバ変数aについてソートする方法を教えてください。
大きく2通りの方法があります。
一つは、A の operator< を定義してソートする方法です。
class A; // ↑の定義の通り
bool operator<(const A& lhs, const A& rhs) {
    return lhs.a < rhs.a;
}

int main() {
    std::list<A> list;
    list.push_back(A(2));
    list.push_back(A(3));
    list.push_back(A(1));
    list.sort(); // 1 2 3
}
もう一つはファンクタを指定する方法です。
class A; // ↑の定義の通り

// ファンクタを作ってソート
struct pred {
    bool operator()(const A& lhs, const A& rhs) const {
        return lhs.a < rhs.a;
    }
};
int main() {
    std::list<A> list;
    ...
    list.sort(pred()); // 1 2 3
}

// 別に関数ポインタでも構わない
bool pred2(const A& lhs, const A& rhs) {
    return lhs.a > rhs.a; // 降順にしてみる
}
int main() {
    std::list<A> list;
    ...
    list.sort(pred2); // 3 2 1
}
クラス A 自体に順序を持たせたい場合は最初の方法を使って、ソートする際に順序を決めたい場合は2番目の方法を使えばいいと思います。
もちろん両方の方法を混ぜて使うこともできます。

Re:listでのクラスのメンバ変数のソート

Posted: 2010年11月16日(火) 01:04
by めるぽん
>演算子のオーバーロードをする必要性
他のライブラリが、今回みたいに < で比較できることを要求していて、ファンクタを取る関数が用意されていない場合は、必須になりますね。
ただ、演算子オーバーロードはむやみに使うと意味が分からなくなるので、ある本では「本当に演算子オーバーロードを使うのが正しいと確信できる場合以外は使わないこと」みたいに書いていたはずです。


>演算子のオーバーロードをすることのメリット
正しく演算子オーバーロードが使われたプログラムである場合、コードが読みやすくなります。
それから、
template<class T>
T abs(T v) {
    v < 0 ? -v : v;
}
みたいなコードを書いたとき、これは組み込み型だけでなく、operator< と単項 operator- が定義されたクラスでも受け取ることができます。
もし演算子オーバーロードが無かった場合、
template<class T>
T abs2(T v) {
    v.less(0) ? v.negate() : v;
}
みたいなコードを別に書くことになるでしょう。

Re:listでのクラスのメンバ変数のソート

Posted: 2010年11月16日(火) 19:16
by bbcs
めるぽんさん、丁寧な回答ありがとうございます
思ったとおりの事ができました
これでだいぶ進歩できそうです

本当にありがとうございました