札幌C++勉強会#1に行って来た

C++の勉強会があるということで思い切って行ってみた。内容は東京で行われている Boost勉強会の様子をみんなでustで鑑賞するというもの。内容はかなりレベルが高かった‥。各発表の合間に勉強会に来ていた方々といろいろお話できてよかった。買ってからスマートポインタと bindの章くらいしか読んでいなかった boost本の未知のページを読むきっかけにもなってとてもよかった。

ちょっと後半体調が悪くなったけれど、夜の部の懇親会にも参加させてもらい、非常に有意義な時間を過ごさせていただきました。Boostの話はもちろん、カルネージハートの話で盛り上がったりととても楽しかった。みなさん本当に勉強熱心だなぁ。

Mac に boost を入れる

パソコンを持って行ったので無線LANに繋がせてもらい、勉強会中はあれこれ調べながらかつtwitterのTLを追いかけながら発表を聞けたのはよかった。途中、どうしても Boostのサンプルを動かしたくなって MacPort でインストールしてみた。

$ sudo port install boost
  • .bashrc に以下を追加
export PATH=/opt/local/bin:/opt/local/sbin/:$PATH
export MANPATH=/opt/local/man:$MANPATH
export LIBRARY_PATH=/opt/local/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=/opt/local/lib:$LD_LIBRARY_PATH
export C_INCLUDE_PATH=/opt/local/include:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=/opt/local/include:$CPLUS_INCLUDE_PATH
export DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib
export BOOST_ROOT=/opt/local/include/boost:$BOOST_ROOT

発表の中で出て来ていた tuple や optional のサンプルを Boost本を読みながら動かしてみた。やっぱり理解するには動かすのが一番だと思った。

tuple と optional のサンプル

  • tuple のサンプル
#include <iostream>
#include <string>

#include "boost/tuple/tuple.hpp"
using namespace std;

boost::tuple<int, double, std::string> getTriple(void){
  return boost::make_tuple( 100, 2.45, "関数から" );
}

void printTriple(boost::tuple<int, double, std::string> &triple){
  cout << triple.get<0>() << endl;
  cout << triple.get<1>() << endl;
  cout << triple.get<2>() << endl;
}

int main() {
  boost::tuple<int, double, std::string> triple(40,3.14,"すごい");
  boost::tuple<int, double, std::string> triple2 = getTriple();

  printTriple( triple );
  printTriple( triple2 );

  return 0;
}

戻りを複数個返したい時とかに凄く使えそう。これはいい。

  • optional のサンプル
#include <iostream>
#include <string>

#include "boost/optional.hpp"
using namespace std;
using namespace boost;

// √x を越えない最大の整数を返す関数
// ただし、xが負の数の時は、「不正です」という値を返す
optional<int> sqrt( int x )
{
  if( x < 0 )
    return optional<int>();

  int i;
  for(i=0; i*i<=x; ++i) {}
    return optional<int>(i-1);
}

int main()
{
  for(int j=-5; j<=5; ++j)
  {
    optional<int> x = sqrt(j);
    if( x )  // 正しいint値を保持しているかどうかチェック
      cout << *x << endl; 
    else
      cout << "invalid" << endl;
  }
  return 0;
}

intの戻り値を欲しい関数を作るときに、エラー時の値を別途返す必要がなくなる。戻り値にエラーの意味を含めるとかいう無理矢理な仕様を作らなく済むのがいい。戻り値を if で判定して通ったら正しい値を取得できているというロジックを組むことができる。
同じようなことを shared_ptr を使うことでも可能だけど、optional の場合は動的メモリを取る訳ではないから処理が軽いという。

鑑賞会メモ

東京で発表している方々はC++界隈では結構すごい人達らしい。知らない用語が飛び交っていて、boost本とにらめっこしながら追いついて行くのがやっとだった。半分くらいはよくわからなかったけど、印象に残ったことをメモ。

  • Fusionの話
    • tuple が出て来てそれを調べている間に終わってしまった‥
  • C++をDisる
    • C++のいけてないところをひたすら言っていた。これだけ言えるって相当使い込んでいるんだろうなぁ。
    • テンプレート関数。forall じゃない。Tのメンバを呼ぶ構文が書けるから結局入力クラスの型が制限されてしまう。v.foo()。それを制限する方法がない。
    • テンプレートを駆使すると分割コンパイルできなくてコンパイル時間がとても長くなる。cppを一つにまとめるとかいうテクニックもあり。
    • テンプレートでusing namespace できない。ヘッダではしちゃいけないらしい。
    • テンプレートはドキュメント化しずらい。型に意味を持たすのが困難。名前で表現する手もあるが、継承関係とかを指定できない。
    • ラムダ式がきもい
  • Boost.Proto
    • Expression Template
    • 結局よくわからず。後で調べる。
  • 例外を改善する
    • lexical_cast で文字列から数字へキャストするのにいちいち例外投げるのしんどい。
    • boost::optionalを使う。 if でチェックして * で参照する。実行時メモリ確保しなくて済む。生ポインタを返すこともできるが、受け取り側で解放しなくてはならない。そのため、shard_ptr を使うことも考えられるが、オーバースペック。
  • shared_ptrについて
    • カスタムデリーターを有効につかおう。所有者いなくなったら呼ばれるデリーターを自前で用意する。
    • ハンドルのクローズで使う。例外時に自前でクローズするの無理な場合にカスタムデリーターにやらせる。
    • 保持はするが責任を持たないレガシー構造体のメンバの所有権をレガシーデリーターで持つ。
    • Nullデリーター。誰かが管理しているリソースや、ポインタのふりをしているだけのデータの場合は Nullデリーターで「何もしない」。
    • void* を含む構造体。バイナリオブジェクト(Blob)の構造体にshared_ptr を追加して create時に関連付けを行う。
  • TR18015:2006を読む
    • Cキャストは使うな
    • ネームスペース使え
    • 仮想関数にしても遅くなるとは限らない
  • ゲーム開発
    • EASTL。ゲームに特化したSTL
    • スマートリンカ。template で使ってないメソッドはリンクしないので、コードの肥大化を防ぐ
  • C++ではまる
    • Sift-jisのコメントやばい。EUCなどで解釈すると \ でエスケープされちゃって挙動が変わる。見つけ難いバグが発生。
    • localeの影響。lexcal_cast で挙動変わる

その他参加メンバーから聞いた情報など

  • C++0xとは、仕様策定中の次バージョン。いろいろ便利な機能が乗っているらしい。


それにしても、東京の Boost勉強会の参加者は 100名を超えていたらしく、懇親会も50名以上参加でキャンセル待ちが出ていたという‥。どんだけ Boost盛り上がっているんだ‥‥、東京恐るべし。