CompTupleBy〜tupleのソート

(後日記)注意:以下ではCompTupleByを紹介していますが、C++11の使える環境ではラムダ式というもっと便利なものがあるので、こうした工夫は前時代の遺物になります。(作った時は便利だったんだけどね)なので以下歴史家の人以外は読まないで下さい。

やあみんな元気にしてるかな。
職場の仲間とは毎日いい雰囲気でうまくやれているか?今日はtupleのコンテナをソートする便利ファンクタCompTupleBy を紹介するぞ。
特徴は任意指定要素でソート出来てしまうということさ。あ、これはラムダは使わない話なラムダ使わない。VS10でのソースは以下のような感じだ。

//
// CompTupleBy.h       (C) 2010 nurs
//
#pragma once
#pragma warning( disable : 4244 )
#include <iostream>
#include <tuple>
template< int id > struct CompTupleBy
{
  template<class T> 
  bool operator()( const T& a, const T& b ) const {
    return std::get<id>(a) < std::get<id>(b);
  }
};

たったこれだけだ。まあそうだろうな。そんな大それたものじゃないさ。使い方のサンプルは以下の通り。

  // 例えばこんなタプル型を考えます
  typedef tuple< int, string, float > Tuptype;
  // tupleのコンテナを用意
  vector< Tuptype > tupv;
  // 0番目の要素でソート
  sort( tupv.begin(), tupv.end(), CompTupleBy<0>() );
  // 1番目の要素でソート
  sort( tupv.begin(), tupv.end(), CompTupleBy<1>() );

てな具合。どうだろうとても簡単で便利そうじゃないかこれ。参考までに実験ソースの全容は以下のような感じだよ。

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

#include "poc_foreach.h"
#include "sort_tuple_by.h"

// 例えばこんなタプル型を考えます
typedef tuple< int, string, float > Tuptype;

// 結果確認用
void lc_show_result( const vector< Tuptype >& tupv )
{
  NURS_FOREACH( tupv, const Tuptype& itup ){
     cout
       << get<0>(itup) <<"\t" 
       << get<1>(itup) <<"\t"
       << get<2>(itup)
       << endl;
  }// itup
  return;
}

// メイン関数
int main( void )
{
  // tupleのコンテナを用意
  vector< Tuptype > tupv;
  {
    tupv.push_back( make_tuple( 0, "Taro", 1.34 ) );
    tupv.push_back( make_tuple( 77, "Aaron", 1.33 ) );
    tupv.push_back( make_tuple( 19, "Buchn", 0.33 ) );
    tupv.push_back( make_tuple( 3, "Vermi", 1.23 ) );
  }

  // 0番目の要素でソート
  cout<<"  ▼"<<endl;
  sort( tupv.begin(), tupv.end(), CompTupleBy<0>() );// ★ここな
  ::lc_show_result( tupv );
  cout<<endl;

  // 1番目の要素でソート
  cout<<"\t  ▼"<<endl;
  sort( tupv.begin(), tupv.end(), CompTupleBy<1>() );// ★ここな
  ::lc_show_result( tupv );
  cout<<endl;

  // 2番目の要素でソート
  cout<<"\t\t  ▼"<<endl;
  sort( tupv.begin(), tupv.end(), CompTupleBy<2>() );// ★ここな
  ::lc_show_result( tupv );
  cout<<endl;

  getchar();
  return 0;
}

NURS_FOREACHはこちらを参考にしてくれ。そして出力は以下。

vector< tuple > とか、tupleのコンテナはもうこれ一つでリレーショナルデータベースの構造そのものなので、いろいろと使われてる場面が多いんじゃないかと思うのだけどどうなんだろうね。
しかも今回のやつがあれば任意キーでソートとかすぐ簡単にできちゃうしね。ちょっとしたことやるんならtupleでなくて自作のデータ構造をコンテナに詰めた方がいいんじゃねという話もあるけどな。
まあtupleなー、、tupleもねー、使うならBoost.Fusion使いましょうよみたいな話もあるらしいのだけれども、fusionの方も早くVCで標準となって欲しいものだよな。じゃっ!

Effective STL: 50 Specific Ways to Improve Your Use of Standard Template Library

Effective STL: 50 Specific Ways to Improve Your Use of Standard Template Library