メモの日々


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は使ったことない。

[book] 眠りの森 (東野圭吾)

眠りの森(東野圭吾/著) 読んだ。高柳バレエ団で起きた不可解な殺人事件を加賀刑事らが調べる話。普通だ。加賀の誠実そうな所は心地よい。3点。


2009年06月06日(土) [長年日記]

  • ズボンとシャツを買った。安いやつ。最近は安物でもあまり気にならない。

[サッカー] ワールドカップアジア最終予選 日本vsウズベキスタン(タシケント)

勝てばワールドカップ出場が決まる試合。日本の先発は

         岡崎
  大久保 憲剛 俊輔
      遠藤 長谷部
長友 闘莉王 中澤 駒野
         楢崎

で内田が体調不良で休み。最初はよかったが途中から日本はボールを繋げず押し込まれる展開。中澤大忙し。ウズベキスタンがシュートをふかすことが多く助けられた。岡崎はいい仕事をした。岡崎が代表で活躍するとはなあ。最後は長谷部が退場になり岡田監督も退席と大変な展開になった。


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(Mecklenburg,Robert/著 Mecklenburg,RobertWilliam/著 ほか) オライリーの 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

やること

  • アイスを食べる
  • 請求書