ログイン
編集不可のページディスカッション情報添付ファイル
clear/note/2011-02

MMA

2011年2月

02/01

02/05

Wikiでのドキュメンテーション時の等幅文字の使用

02/06

CapsLock不用論に関する実験

ImageMagickで画像の切り出しを行う

02/07

X11フォワーディングしてきたアプリケーションで日本語を入力する

02/09

02/11

勉強したことを記録していくと、何もやらなかった期間はぽっかり記録が空くので良いかもしれない。とりあえず、積みっぱなしの「初めてのPython」をちゃんと読んで勉強しようと思う。それからOCamlももっと書く。買った本に練習問題が付いているので、解いてみるのも良いか。

オレンジジュースに求めるもの

今日、もとい昨日飲んだものが期待に反してあまりにも残念だったので、個人的にオレンジジュースに対して求めるものを書いておく。

三日くらい経ってから読み返したら、何でこんなものを書いたのかと自分でも思うかもしれないが、こういうのはそのときの感情が大事なのだろう、ということで残しておく。

なんだこれ

作ったものをgitの管理下に入れようと思いたち、nestでcommitした際のエラーメッセージ(commit自体はできた)。

".git/COMMIT_EDITMSG" [変換済] 21L, 514C
/usr/local/share/vim/vim73/syntax/diff.vim の処理中にエラーが検出されました:
行   62:
E401: パターン区切りがみつかりません: "^Δεν υπάρχει χαρακτήρας νέας γραμμής στ       >
ο τέλος του αρχείου"
E475: 無効な引数です: diffNoEOL^I"^Δεν υπάρχει χαρακτήρας νέας γραμμής στο τ       >
έλος του αρχείου"

gitではなくvimがエラーメッセージを吐いている。件のファイル/usr/local/share/vim/vim73/syntax/diff.vimはUTF-8だが、これが原因なのだろうか。エラーが出ているのはギリシャ語(el)のセクションである。試しに、適当なdiffファイルを作ってvimで開いたところ全く同じ出力が得られた。もう少し調べてみようと思う。

02/12

02/13

02/14

よくわからない

C++において、C標準ライブラリの中身はstd名前空間に入る。これを用いるには、例えばstdio.hではなくcstdioをインクルードする。ただし、互換性のためC++でもstdio.hを使うことができる。この場合グローバル名前空間に入る。

nestで/usr/include/c++/4.2/cstdioを読むと、だいたい以下のようなことをやっていた。

// cstdio
#include <stdio.h>
// ...
namespace std {
    using ::printf;
    // ...
}

よって、こういうコードが通る。

   1 #include <cstdio>
   2 int main()
   3 {
   4     // ここにあるはず
   5     std::printf("hello, world from namespace std\n");
   6     // ここにもある
   7     printf("hello, world from global\n"); // ::printf(...)に同じ
   8 
   9     return 0;
  10 }

ここまでが前提。

snprintf()を使うコードを書いていた。これはC99で標準となった。C++においてC99の機能は、一部がTR1や0xで取り込まれている(完全ではないが今回は問題ないはず)。そこでtr1/cstdioをインクルードしたのだが、std::tr1::snprintf()のように呼び出すと「snprintftr1の中に無い」とコンパイルエラーが出る。std::snprintf()としてもやはりstdの中には無いと言われる。前提に立ち返ると、これはすなわちstd::tr1とかstdの中でusing宣言がされていないということだ。一体どうなっているのだろう。tr1/cstdioを読むと上に書いたような形でusing宣言されている。#ifdefに囲まれているのでその辺の問題なのか。

色々考えていて、もう一つ気になった。そもそも先に上げた前提は(事実ではあるが)正しいのかということだ。std::と修飾することを「必要」としている文章も見つかった(こことか)。この場合、標準Cライブラリの中身がグローバル名前空間で見えてはいけないことになる。

これに関してWikipediaの記事に興味深い記述があった。

... また、標準Cライブラリとの互換性を持たせるため、<xxx.h> 形式のヘッダも使用することができ、std 名前空間内で宣言された識別子はusing指令によってグローバル名前空間に引き出される。

「引き出される」ということはつまり初めからグローバル名前空間にある訳ではないということだ。英語版を見ると

... The only difference between these headers and the traditional C Standard Library headers is that where possible the functions should be placed into the std:: namespace (although few compilers actually do this).

std名前空間内に配置されるべき(グローバル名前空間から見えるべきではない)だが、実際にそのように実装しているコンパイラはほとんど無い、ということだろうか。

結論: 試験勉強をすべきときに色々気にし出すとよくない。


OpenOffice.org 3.3.0

家でコンパイルしてきたのが端末に入った。libsigsegvが無いと言われて残念な思いをしたが、別途入れたらOKだった。動作も少し試した限りでは問題無し。


02/15

これが画面を分割しすぎた者の末路だ

separate.png

02/21

設定リーダの実装

別ページ

02/23

STLのアルゴリズムを駆使したら開発効率が上がった気がする。

STLアルゴリズムと述語の話

文字列からトークンを切り出すために「ある位置から空白(ここではスペースとタブ)か、デリミタまで」の部分を得たかったので、ちょうど使えそうなstd::find_if()を試すことにした。find_if()はイテレータfirstlastと述語(真偽値を返す関数あるいは関数オブジェクト)predを受け取り、[first, last)の範囲で最初にpredが真となるような要素のイテレータを返す。

まず、述語として次の関数オブジェクト(ファンクタ)is_token_endを用意した。std::binary_function(二引数の関数オブジェクトのための基底クラスとして用意されている)を継承して作る。

// トークンの終わりかどうか
struct is_token_end : public std::binary_function<char, char, bool>
{
    bool operator()(char c, char delim) const
    {
        return is_ws(c) || (c == delim); // is_ws()は単純に(c == ' ' || c == '\t')の値を返すだけの関数
    }
};

ここで問題になるのがpredは一引数の関数へのポインタか、または一引数のoperator()を持つ関数オブジェクトでなければならないことだ。しかしデリミタが定まっていない以上引数として与えるしかないので、二引数となる。これではfind_if()に渡すことが出来ない。これは、「is_token_enddelimを受け取って、『文字cを受け取りis_token_end(c, delim)の値を返すような(operator()を持つ)一引数の関数オブジェクト』を返す関数」があれば解決する。これに相当するのがstd::bind1st()あるいはstd::bind2nd()だ。以下のようにして使う。

// ...
string::iterator key_end = find_if(i, end, bind2nd(is_token_end(), delim));
// ...

いくつかのミスによるコンパイルエラーを経たものの期待通りに動作し、めでたしめでたし…と思いつつ、色々googleで調べていたところ、わざわざbindしないでいい(binary_functionである必要が無い)という方法を見つけた。具体的にはここ。すなわち、関数オブジェクトにメンバ変数として比較対象を持たせることでunary_function(一引数の関数オブジェクト…略。ちなみにbinaryまでしかない)にできる。

// トークンの終わりかどうか
struct is_token_end : public std::unary_function<char, bool>
{
    explicit is_token_end(char delim) : delim_(delim) {}
    bool operator()(char c) const
    {
        return is_ws(c) || (c == delim_);
    }
private:
    const char delim_;
};

bindする必要がなくなるので、呼出側はすっきりする。

// ...
string::iterator key_end = find_if(i, end, is_token_end(delim));
// ...

これも期待通りに動き、こちらの方が綺麗なのでなるほどと思っていたのだが、一つだけ気になることがある。つまり「述語がメンバ変数を持っていて良いのか」ということだ。値を書き換える訳でもないから大丈夫だとは思うけれど(そもそもconstな時点で書き換えられないが)。ともあれ、なんだかfunctionalな感じでSTLのアルゴリズムをいじるのは楽しい。考えた人の頭の良さを感じて止まない。

02/28

ftdi.hpp

kagisysに使われているlibftdiにはC++のラッパーがあった。pimplイディオムを使うために<boost/shared_ptr>を使っているので、使うとしたら依存関係にboostが加わることに。一応shared_ptrはTR1に入っている(多分互換性はある)ので、ライブラリを書き換える手もある。

clear/note/2011-02 (最終更新日時 2011-04-16 15:27:58 更新者 clear)