2009年06月03日(水) [長年日記]
- 単調な毎日。
■ [c++] C++でのクラスのメンバへのポインタ
クラスのメンバへのポインタを使った。すぐに忘れそうなのでメモ。
- 例えば、クラスAのstring型のメンバ変数へのポインタを格納する変数sは「string A::* s」のように宣言する。
- クラスAのstring型のメンバ変数sssへのポインタは、「&A::sss」のように書けば取得できる。故に「string A::* s = &A::sss」と代入できる。
- 同様にしてメンバ関数へのポインタも扱える。「int (A::*f)(const string&) = &A::func」みたいな。
- ポインタを使うときには対応するクラスのインスタンスが必要になる。クラスAのインスタンスaがあったとき、「a.*s」や「(a.*f)("aaa")」のように使う。
以下サンプルプログラムと実行結果。
#include <iostream> #include <string> #include <vector> struct A { int i1; int i2; int plus1(int i) { return i + 1; } int minus1(int i) { return i - 1; } }; // クラスAのインスタンスinstanceの、 // int型のメンバ変数memberに、 // 整数valueを設定する。 void set_integer_to_A(A& instance, int A::* member, int value) { instance.*member = value; } // クラスAのインスタンスinstanceの、 // int型の引数を取りint型の値を返すメンバ関数fに、 // 整数iを渡した戻り値を返す。 int call_func_of_A(A& instance, int (A::*f)(int), int i) { return (instance.*f)(i); } int main() { A a; set_integer_to_A(a, &A::i1, 100); set_integer_to_A(a, &A::i2, 200); std::cout << a.i1 << "\n" << a.i2 << "\n" << call_func_of_A(a, &A::plus1, 10) << "\n" << call_func_of_A(a, &A::minus1, 10) << "\n"; }
100 200 11 9
■ やること
請求書請書
2009年06月04日(木) [長年日記]
- Subversionの外部定義機能を初めて使った。svn propedit コマンドを使ってディレクトリに svn:externals 属性を付与すればよい。素直に想像通りに動いてくれた。
- Mercurialはたまに使うがGitは使ったことない。
2009年06月09日(火) [長年日記]
■ [life] 外国人の銀行振込を手伝った
銀行のATMに行ったら西洋風の外国人男女二人組に声をかけられた。分からないので手伝って欲しいとのこと。
むむこれは謎の液体を浴びせこちらが慌てている隙に金を盗む不良外人コンビか?と警戒したが、そういうことにはならなかった。
ATMの字が読めず困っているということだったが、始めの方は自分たちで操作できていた。そして、振込先の銀行を選ぶ所で分からないという。カタカナが読めないらしい。おれが「ツ」を選んであげて、その後おれにもよく分からない選択肢もあったが一応振り込み完了。サンキューベリーマッチとお礼の言葉を頂いた。
外国人と話すと、相手がどれくらい日本語を話せるのかわからないのでおれもカタコトの日本語になってしまう。今日の人たちは話す方は達者なようだったのでもっと普通に喋ればよかったと反省。
2009年06月11日(木) [長年日記]
- 定額給付金、振り込まれてた。
- 右利きのおまえらが左手でマウスを使うべきいくつかの理由を読んで、マウスを左手で使うようにしてみた。おれは本当は左利きなのでうまくフィットするはず。
- でも今の所はギクシャク。キーボードを打つときにも「逆」のイメージが伝わってしまうのだなあ。
■ [c++] Ubuntu で BOOST_CHECK_CLOSE を使うとエラーになった
Ubuntu 9.04でBoostのユニットテストフレームワークを使っていたら、BOOST_CHECK_CLOSE を呼ぶ箇所で
error: 'check_is_close' is not a member of 'boost::test_tools'
というコンパイルエラーになってしまった。パッケージのバージョンは libboost-test1.34.1。
検索すると、#338417 - libboost-test-dev: BOOST_CHECK_CLOSE out of workというDebianのバグレポートが見つかり、ここに
#include <boost/test/floating_point_comparison.hpp>
を加えればいいようなことが書いてあったので、テストプログラムに上の include を追加したら直った。
けどこんな include を書かないといけないのはおかしいよなあ。
2009年06月14日(日) [長年日記]
- マウス左手継続中。まだ慣れない。
■ [c++][c][dev] C++用Makefileのサンプル
GNU makeは奥が深すぎて嫌になるな。今日考えた、C++のプログラムをビルドするためのGNU make用のMakefileをメモ。Cでも同様のはず。おかしな所があったら教えてください。
ソースファイルとMakefileの構成は次のようになっているとする。Makefileは1つだけ。
. |-- Makefile `-- src |-- aaa | |-- a.cpp | |-- a.h | `-- ccc | |-- c.cpp | `-- c.h |-- bbb | |-- b.cpp | `-- b.h `-- main.cpp
これを make すると次のようになる。build ディレクトリが作られそこに *.o と *.d と実行ファイルsampleが作られる。
. |-- Makefile |-- build | |-- sample | `-- src | |-- aaa | | |-- a.o | | |-- a.o.d | | `-- ccc | | |-- c.o | | `-- c.o.d | |-- bbb | | |-- b.o | | `-- b.o.d | |-- main.o | `-- main.o.d `-- src | (src以下は変わらないので省略)
次にメモとMakefileを示す。
- *.dはヘッダファイルも考慮した依存関係を記述したファイル。GNU makeのマニュアルに説明がある。そこに書いてあるよりもシンプルな処理にしたけど。
- ビルド対象とするディレクトリをMakefileに列挙する必要がある。ここを自動化することもできると思うけど、列挙する方が便利なこともある。
- ソースファイルは自動で見つける。拡張子が cpp のファイルは全てビルド対象とみなす。
- ターゲットは all と clean しか作ってない。
# GNU make 用です build_base_dir = build program = $(build_base_dir)/sample # ここにビルド対象とするディレクトリを全て書く src_dirs = src src_dirs += src/aaa src_dirs += src/aaa/ccc src_dirs += src/bbb CPPFLAGS = -I src CXXFLAGS = -Wall -g sources = $(wildcard $(addsuffix /*.cpp, $(src_dirs))) objects = $(sources:%.cpp=$(build_base_dir)/%.o) depends = $(addsuffix .d, $(objects)) build_dirs = $(addprefix $(build_base_dir)/, $(src_dirs)) .PHONY: all all: $(build_dirs) $(program) .PHONY: clean clean: rm -rf $(build_base_dir) $(program): $(objects) $(CXX) $(LDFLAGS) -o $@ $^ $(build_base_dir)/%.o: %.cpp $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< $(CXX) $(CPPFLAGS) -MM $< \ | sed 's|^\([^\.]*\)\.o|$(@D)/\1\.o|' > $@.d $(build_dirs): mkdir -p $@ -include $(depends)
実行すると手元の環境では次のように表示された。
$ make --version GNU Make 3.81 Copyright (C) 2006 Free Software Foundation, Inc. これはフリーソフトウェアです. 利用許諾についてはソースを ご覧ください. 商業性や特定の目的への適合性の如何に関わらず, 無保証です. This program built for i486-pc-linux-gnu $ make mkdir -p build/src mkdir -p build/src/aaa mkdir -p build/src/aaa/ccc mkdir -p build/src/bbb g++ -I src -Wall -g -c -o build/src/main.o src/main.cpp g++ -I src -MM src/main.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/\1\.o|' > build/src/main.o.d g++ -I src -Wall -g -c -o build/src/aaa/a.o src/aaa/a.cpp g++ -I src -MM src/aaa/a.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/aaa/\1\.o|' > build/src/aaa/a.o.d g++ -I src -Wall -g -c -o build/src/aaa/ccc/c.o src/aaa/ccc/c.cpp g++ -I src -MM src/aaa/ccc/c.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/aaa/ccc/\1\.o|' > build/src/aaa/ccc/c.o.d g++ -I src -Wall -g -c -o build/src/bbb/b.o src/bbb/b.cpp g++ -I src -MM src/bbb/b.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/bbb/\1\.o|' > build/src/bbb/b.o.d g++ -o build/sample build/src/main.o build/src/aaa/a.o build/src/aaa/ccc/c.o build/src/bbb/b.o
■ [dev] GNU makeの参考資料
オライリーの GNU Make 第3版 が一番参考になると思うけど、持ってない。立ち読みはした。
ウェブ上のリソースをメモ。
- GNU `make' (GNU)
- 本家にあるマニュアル。
- GNU make 日本語訳(Coop編) (ecoop.net)
- 上のマニュアルの日本語訳。とても役に立つが少し古い。
- GNU Make の使い方 (みねこあ)
- オライリー本にあるテクニックが紹介されていたので参考にした。結局あまり難しいことはしなかったけれど。
2009年06月15日(月) [長年日記]
■ [dev][link] is open と is closed
JavaのAPIを見ると、isOpen(),isClosed()というメソッドはあるが isOpened() と isClose() は無い。
変なの、と思ったけど、英語とはそういうもののようだ。そのことを話題にしたページがあったのでメモ。
お店なんかで、当店は何時から何時まで営業して(開いて)おります、なんていう場合、
The shop is open from 10 am to 7 pm.
というように、 The shop is open … と言います。 しかし、日曜日は休業(閉まって)です、なんていう場合は、
The shop is closed on Sundays.
なんていうように、 The shop is closed … なんですよね。 The shop is close … じゃないんです。 なんでかというと、上記の open は形容詞、closed で形容詞だからです。
■ やること
- 住民税
- 自動引落
2009年06月20日(土) [長年日記]
■ [life] 眼鏡を買った
今の眼鏡は随分汚れてしまっていてずっと新しい眼鏡が欲しかった。今日やっと買った。
色々試し掛けしたけど、おれは眼鏡似合わないなーと思った。 結局今のと似た形のものにしてしまった。
視力は0.05以下とのこと。最薄のレンズにしてもらった。1枚1万7500円とのことでレンズだけで3万5000円。大事にしないと。
町に出たついでにローテーブルも購入。1万円ちょっとの安いやつ。これもやっと買えた。
■ やること
住民税自動引落
2009年06月21日(日) [長年日記]
■ [c++][c][dev] C++用Makefileのサンプル (2)
ちょっと前にMakefileをメモしたけど、文字コードを変換してからビルドしたいケースもあるので、それに対応したMakefileも作ってみた。
- 文字コードをCP932からUTF-8へ、改行コードをCRLFからLFへ変換している。変換にはNKFを使用。
- 何もしないとコンパイルエラー時に変換後のソースファイルパスが表示されるが、それだとVimからmakeを実行したときに変換後のソースにジャンプしてしまい不便。なので、sedを使ってソースファイルパスを変換前のものに置換している。更に念のため変換後のソースから書込権限を除いておく。
- sedで上の置換をする際にパイプを使っているが、そうするとコンパイルエラーになっても終了コードがエラーにならなくなり困る。そこでBASHのpipefailオプションを使って終了コードがエラーになるようにした。
# GNU make用です build_base_dir = build program = $(build_base_dir)/sample # ここにビルド対象とするディレクトリを全て書く src_dirs = src src_dirs += src/aaa src_dirs += src/aaa/ccc src_dirs += src/bbb SHELL=/bin/bash CPPFLAGS = -I $(build_base_dir)/src CXXFLAGS = -Wall -g headers = $(wildcard $(addsuffix /*.h, $(src_dirs))) sources = $(wildcard $(addsuffix /*.cpp, $(src_dirs))) headers_utf8 = $(headers:%.h=$(build_base_dir)/%.h) sources_utf8 = $(sources:%.cpp=$(build_base_dir)/%.cpp) objects = $(sources_utf8:%.cpp=%.o) depends = $(addsuffix .d, $(objects)) build_dirs = $(addprefix $(build_base_dir)/, $(src_dirs)) .PHONY: all all: $(build_dirs) $(headers_utf8) $(sources_utf8) $(program) .PHONY: clean clean: rm -rf $(build_base_dir) $(program): $(objects) $(CXX) $(LDFLAGS) -o $@ $^ %.o: %.cpp set -o pipefail; $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< 2>&1 \ | sed --unbuffered 's|$(build_base_dir)/||' set -o pipefail; $(CXX) $(CPPFLAGS) -MM $< \ | sed 's|^\([^\.]*\)\.o|$(@D)/\1\.o|' > $@.d $(build_base_dir)/%.cpp: %.cpp rm -f $@ nkf --ic=CP932 --oc=UTF-8 -Lu -d $< > $@ chmod a-w $@ $(build_base_dir)/%.h: %.h rm -f $@ nkf --ic=CP932 --oc=UTF-8 -Lu -d $< > $@ chmod a-w $@ $(build_dirs): mkdir -p $@ -include $(depends)
先日の例と同じ構成のソースファイルをビルドすると、
. |-- Makefile |-- build | |-- sample | `-- src | |-- aaa | | |-- a.cpp | | |-- a.h | | |-- a.o | | |-- a.o.d | | `-- ccc | | |-- c.cpp | | |-- c.h | | |-- c.o | | `-- c.o.d | |-- bbb | | |-- b.cpp | | |-- b.h | | |-- b.o | | `-- b.o.d | |-- main.cpp | |-- main.o | `-- main.o.d `-- src |-- aaa | |-- a.cpp | |-- a.h | `-- ccc | |-- c.cpp | `-- c.h |-- bbb | |-- b.cpp | `-- b.h `-- main.cpp
のようになる。buildの下にあるのが変換後のソースファイル。
手元の環境で実行すると次のように出力された。
mkdir -p build/src mkdir -p build/src/aaa mkdir -p build/src/aaa/ccc mkdir -p build/src/bbb rm -f build/src/aaa/a.h nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/a.h > build/src/aaa/a.h chmod a-w build/src/aaa/a.h rm -f build/src/aaa/ccc/c.h nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/ccc/c.h > build/src/aaa/ccc/c.h chmod a-w build/src/aaa/ccc/c.h rm -f build/src/bbb/b.h nkf --ic=CP932 --oc=UTF-8 -Lu -d src/bbb/b.h > build/src/bbb/b.h chmod a-w build/src/bbb/b.h rm -f build/src/main.cpp nkf --ic=CP932 --oc=UTF-8 -Lu -d src/main.cpp > build/src/main.cpp chmod a-w build/src/main.cpp rm -f build/src/aaa/a.cpp nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/a.cpp > build/src/aaa/a.cpp chmod a-w build/src/aaa/a.cpp rm -f build/src/aaa/ccc/c.cpp nkf --ic=CP932 --oc=UTF-8 -Lu -d src/aaa/ccc/c.cpp > build/src/aaa/ccc/c.cpp chmod a-w build/src/aaa/ccc/c.cpp rm -f build/src/bbb/b.cpp nkf --ic=CP932 --oc=UTF-8 -Lu -d src/bbb/b.cpp > build/src/bbb/b.cpp chmod a-w build/src/bbb/b.cpp set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/main.o build/src/main.cpp 2>&1 \ | sed --unbuffered 's|build/||' set -o pipefail; g++ -I build/src -MM build/src/main.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/\1\.o|' > build/src/main.o.d set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/aaa/a.o build/src/aaa/a.cpp 2>&1 \ | sed --unbuffered 's|build/||' set -o pipefail; g++ -I build/src -MM build/src/aaa/a.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/aaa/\1\.o|' > build/src/aaa/a.o.d set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/aaa/ccc/c.o build/src/aaa/ccc/c.cpp 2>&1 \ | sed --unbuffered 's|build/||' set -o pipefail; g++ -I build/src -MM build/src/aaa/ccc/c.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/aaa/ccc/\1\.o|' > build/src/aaa/ccc/c.o.d set -o pipefail; g++ -I build/src -Wall -g -c -o build/src/bbb/b.o build/src/bbb/b.cpp 2>&1 \ | sed --unbuffered 's|build/||' set -o pipefail; g++ -I build/src -MM build/src/bbb/b.cpp \ | sed 's|^\([^\.]*\)\.o|build/src/bbb/\1\.o|' > build/src/bbb/b.o.d g++ -o build/sample build/src/main.o build/src/aaa/a.o build/src/aaa/ccc/c.o build/src/bbb/b.o
■ やること
- アイスを食べる
- 請求書