<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>はらぺこ日誌 &#187; Boost</title>
	<atom:link href="https://blog.harapeko.jp/tag/boost/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.harapeko.jp</link>
	<description>株式会社はらぺこ 公式ブログ</description>
	<lastBuildDate>Mon, 30 Oct 2017 14:32:56 +0000</lastBuildDate>
	<language>ja</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.2</generator>
	<item>
		<title>Observer パターンでコンソール MVC っぽいことをやってみる &#8211; C++ のための API デザイン</title>
		<link>https://blog.harapeko.jp/2014/08/06/observer-apides/</link>
		<comments>https://blog.harapeko.jp/2014/08/06/observer-apides/#comments</comments>
		<pubDate>Wed, 06 Aug 2014 09:06:45 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++11]]></category>
		<category><![CDATA[設計]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=319</guid>
		<description><![CDATA[ライブラリ API の設計手法を学ぼうシリーズの第2弾です。前回の記事はこちら。以下の教材を利用しています。  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>ライブラリ API の設計手法を学ぼうシリーズの第2弾です。<a href="http://blog.harapeko.jp/2014/06/19/pimpl-factory-apides/">前回の記事はこちら</a>。以下の教材を利用しています。</p>
<ul>
<li><a href ='http://www.amazon.co.jp/gp/search/ref=as_li_qf_sp_sr_il?ie=UTF8&#038;camp=247&#038;creative=1211&#038;index=aps&#038;keywords=C%2B%2B%20API%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3&#038;linkCode=as2&#038;tag=harapekoinc-22'>C++ APIデザイン<br />
<img src='http://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&#038;ASIN=B00EYXMA6Q&#038;Format=_SL250_&#038;ID=AsinImage&#038;MarketPlace=JP&#038;ServiceVersion=20070822&#038;WS=1&#038;tag=harapekoinc-22' border='0' /></a></li>
</ul>
<p>さて、API のラッピングパターンについてはざっと読むだけで終了とし、今回は Observer パターンについてさらってみました。</p>
<h3>MVC っぽいことをやってみたい。</h3>
<p>本書では、オブザーバーパターンの説明に入る前に、 MVC アーキテクチャについての説明がありました。</p>
<blockquote cite="http://www.amazon.co.jp/gp/search/ref=as_li_qf_sp_sr_il?ie=UTF8&#038;camp=247&#038;creative=1211&#038;index=aps&#038;keywords=C%2B%2B%20API%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3&#038;linkCode=as2&#038;tag=harapekoinc-22" title="C++ APIデザイン - 3.5.1 モデル/ビュー/コントローラ (p.120)"><p>
シンプルなアプリケーションでは、コントローラはユーザ入力に基づいてモデルへの変更に影響を与え、こうした変更をビューに通信して、UIを更新できるようにする。しかし、実際のアプリケーションでは、通常、水面下のモデルへの追加変更を反映するために、ビューも更新する必要がある。(…中略…)とはいえ、先ほど述べたように、モデルコードはビューコードを静的にバインディングして呼び出すことはできない。そこでオブザーバーが必要になるのだ。
</p></blockquote>
<p>なるほどなるほど。とまぁ、こんな説明の後に Observer パターンの実装例とその説明に入っていくのを見せられたら、そりゃあまぁ、 MVC っぽいことをやってみたい、って普通思いますよね…??</p>
<p>ただ、上記にあるようにモデルがビューを監視できるようにする必要があるという話であるにもかかわらず、多くの MVC フレームワーク実装を見るに、ビューからのメッセージを受け取って何らかの制御を行うコードは通常コントローラに書かれているように見えます。現実的には、ビジネスロジックはフレームワークを差し替えても流用可能であることが望ましく、オブザーバーにするための抽象クラスの継承でさえ避けたいというのが実情なのではないかと思います。<br />
<span id="more-319"></span><br />
そこで、コントローラをビューに対するオブザーバーとする設計とし、ビューが提供するいくつかのメッセージに対して、メッセージハンドラのような感じでコントローラを登録し、実装できるようにする、という考え方でやってみることにしました。ビューはよく使いそうなパターンのものを幾つか用意しておけば、あとは必要に応じてたまーに新しいものを追加する程度の変更で事足りるでしょうが、コントローラは新しい機能を追加するたびに必ず実装を追加することになります。テキスト p.120 の図にも示されている通り、ビューはコントローラの実装を知らないほうが良いのです。モデルはコントローラが掴んで (もしくは生成して)、ビューから呼び出されるハンドラメソッド内で操作するようにすればよいでしょう。</p>
<h3>コンソール画面で動くものを作ってみる。</h3>
<p>MVC アーキテクチャっぽいものを、といっても、具体的に何を作ろうか、というのは悩みどころです。 GUI のものを作るにしても、 Web アプリケーションを作るにしても、結構大掛かりなシステムになってしまうのではないかという不安があります。お試しで作るんですから、簡単なものがいいんですよね…。</p>
<p>というわけで、コンソール画面で動くものを作ることにしよう、ということでプログラムを書いてみることにしました。それも内容的にもごく簡単なものをということで、お題はズバリ、<strong>時計</strong>です。コンソール画面の真ん中らへんで、現在時刻を表示し続けるというだけの、ごくごく簡単なプログラムです。</p>
<h3>作ってみた。</h3>
<p>そんなわけで、作ってみました。ソースコードは以下の場所にて公開しています。</p>
<ul>
<li><a href="https://github.com/murachi/samples-for-blog/tree/master/c%2B%2B/api-design-for-c%2B%2B/ch03-pattern/observer">samples-for-blog/c++/api-design-for-c++/ch03-pattern/observer at master · murachi/samples-for-blog</a></li>
</ul>
<p>このプログラムは <code>std::thread</code> を使ったマルチスレッドプログラムなので、 gcc でコンパイルするときは以下のように、必ず <code>-pthread</code> オプションを付けてあげて下さい。</p>
<pre>
$ g++ -std=c++11 -pthread -o watch *.cpp
$ ./watch
</pre>
<p>プログラムを実行すると、コンソール画面がクリアーされて、画面の真ん中らへんに現在日時がリアルタイムで表示されます。また、画面の下の方に「Hit any key to finish.」と表示されるとおり、なにか適当なキーを押すとプログラムは終了します。<br />
<a href="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-ubuntu.png"><img src="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-ubuntu.png" alt="Ubuntu で実行" title="observer パターン練習プログラムを Ubuntu 環境で実行してみたところ" width="410" height="303" class="alignnone size-full wp-image-334" /></a><br />
<a href="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-windows.png"><img src="http://blog.harapeko.jp/wp-content/uploads/2014/08/fig-run-windows.png" alt="Windows で実行" title="observer パターン練習プログラムを Windows 環境で実行してみたところ" width="338" height="246" class="alignnone size-full wp-image-338" /></a><br />
なお、動作確認は以下の環境にて行いました。</p>
<ul>
<li>Ubuntu Linux 14.04 LTS x86_64/GCC 4.8.2/bash 4.3.11/kernel 3.13.0</li>
<li>Windows7 Professional SP1 x86_64/Mingw_w64 GCC 4.8.2 (powerd by <a href="http://win-builds.org/">Win-builds</a>)/コマンドプロンプト</li>
</ul>
<h3>プログラムの解説など。</h3>
<h4>モデル</h4>
<p>日時の保持と現在日時への更新、といった辺りをビジネスロジックとして実装しています。 datetime.h と datetime.cpp がそれです。</p>
<p>ここはまぁ、日時の取り扱いに Boost.DateTime を使っているという点以外は特筆すべき点も無いんじゃないかと思います。</p>
<h4>ビュー</h4>
<p>コンソール上で動作するビュー全般、ということで console-view.h と console-view.cpp 、より具体的に静的に文字列を表示するだけのビューということで static-text.h と static-text.cpp を、そしてキー入力を待ち受けるためのビューとして key-listener.h と keylistener.cpp を実装しました。また、ビューはオブザーバーを登録して通知を投げるサブジェクトとして実装しています (subject.h 、 subject.cpp)。</p>
<pre>
class SubjectBase : private boost::noncopyable {
    // ...
};

class ConsoleView : public SubjectBase {
    // ...
};

class StaticText : public ConsoleView {
    // ...
};

class KeyListener : public ConsoleView {
    // ...
};
</pre>
<p>SubjectBase クラスについては、これはもう概ね教科書どおりの実装です。 <code>subscribe()</code> メソッドにてメッセージ ID を指定しつつ observer を登録し、何らかのイベントに応じて、そのイベントに対応するメッセージ ID に指定登録されたすべてのオブザーバーに通知を投げる、ということができる仕組みになっています。派生クラスは自身の <code>notifyObserver()</code> メソッドを呼べば、 observer として登録されているコントローラを呼び出すことができるというわけです。</p>
<p>なお、オブザーバーの登録・削除はスレッドセーフになるよう、 Mutex を使ってロックをかけています。オブザーバーへの通知の際にもロックをかけていますが、通知対象となるオブザーバーの配列をコピーするまででロックを解除し、コピーを見て通知を行うようにしています (通知の実行までロックした状態でやるとデッドロックを起こすことがあったので…<tt>^^;</tt>)。</p>
<p>ConsoleView クラスはコンソール上で動作するビューとしての一通りの機能を持つクラス… であるべきなのですが、考えられるすべての機能を盛り込みまくる動機付けもなかったので、とりあえず以下の機能だけ実装しました。</p>
<ul>
<li>以下のステータスの保持と、それに基づく表示
<ul>
<li>表示文字列</li>
<li>表示位置 (コンソール座標)</li>
<li>色番号 (0～7)</li>
</ul>
</li>
<li>上記のステータスを変更すると、それに応じて表示を更新する</li>
<li>タイマー、およびインターバルタイマー</li>
<li>コンソール画面のサイズの取得</li>
</ul>
<p>ステータスの変更は <code>setStatus()</code> メソッドにて行います。ステータスを変更すると即座に表示に反映される、ようにしたかったのですが、例えばテキストも表示位置も色も変更するよ、という場合に、それぞれの値を個別に受け取るようにメソッドを分けてしまうと、一度の変更で再描画が最大 3回も走ってしまう、というのでは激しくダサいなと思ったので、現在のステータスを構造体として受け取って、その内容を書き換えるコールバック関数を受け取るようにしてあります。このコールバック関数は <code>std::function</code> として受け取るようにしてあるので、キャプチャ付きのラムダを指定することも可能です (<a href="http://blog.harapeko.jp/2014/07/25/lambda-ref-captured-constant/" title="はらぺこ日誌» ブログアーカイブ » C++: lambda の参照キャプチャは const 性を損なわない?">こちらの記事</a>でやろうとしていたやつですね<tt>^^;</tt>)。</p>
<p>タイマーとインターバルタイマーは、それぞれ <code>setTimer()</code> と <code>setInterval()</code> 各メソッドを呼ぶことで発動します。どちらも指定した時間が来ると <code>vm_Timer</code> メッセージの通知を observer に投げます。インターバルタイマーの方はこれを <code>stopInterval()</code> を呼ぶまで何度でも繰り返します。今回のプログラムではインターバルタイマーの方だけ使っています。</p>
<p>StaticText クラスはコンソール上の固定の位置に、指定した色で指定したテキストをただ表示するだけのビューとして実装しました。 <code>changeText()</code> メソッドを使うことで、表示するテキストの内容だけ変更することができるようになっています。もっとも、<code>ConsoleView::setStatus()</code> メソッドが public なので、やろうと思えば表示位置や色も変更できてしまうのですが…。</p>
<p>KeyListener クラスは、キー入力を待ち受けし、入力値を取得することができる入力用のビューです。あまりコメントを尽くしていないのでわかりにくいのですが、 <code>initialize()</code> メソッドをオーバーライドしており、オブザーバーに初期化メッセージを投げる前に、この中でキー待受を行うスレッドを生成します。このスレッドがキーの入力を取得すると、今度はオブザーバーにそのことを伝えるメッセージを投げ、オブザーバー側で <code>getKeyChar()</code> メソッドを呼んで入力値を得ることができるようになっています。</p>
<h4>コンソールマネージャ</h4>
<p>コンソール制御は複数存在しうるビューとは切り離して実装する必要があると判断し、コンソールマネージャとして別途実装しています (console-manager.h 、 console-manager.cpp)。内容的にはシングルトンにしたいところなのですが、今回はビューに対して依存性を注入することを前提とした設計ということにしてみました (<code>main()</code> 関数の中で 1つだけインスタンスを生成するイメージ)。</p>
<p>実際に実装した機能は以下のとおりです。</p>
<ul>
<li>インスタンス生成時に画面をクリアする。</li>
<li>インスタンス破棄時にカーソルの現在の文字の色を元に戻す (Windows では白で決め打ちにしちゃってます…)。</li>
<li>コンソール画面のサイズの取得 (<code>getSize()</code>)。</li>
<li>指定したカーソル位置及び色でコンソールに文字列を出力する (<code>output()</code>)。</li>
<li>エコーバックせずにキー入力を受け付ける (<code>waitKeyInput()</code>)。</li>
</ul>
<p>ConsoleView クラスやその派生クラスが提供する機能の具体的な実装は全てここにあります。</p>
<p>最後の <code>waitKeyInput()</code> は、要するに DOS の <code>getch()</code> 関数です (実際、 Windows では <a href="http://msdn.microsoft.com/ja-jp/library/078sfkak.aspx">_getch()</a> 関数を呼んでいます)。当然ブロックします (なので、 KeyListener クラスはスレッドを咬ましてこいつを呼びに行っています)。</p>
<h4>コントローラ</h4>
<p>時計のリアルタイム表示処理を行うコントローラとして watch-controller.h と watch-controller.cpp 、キーが入力されるまでプログラムを実行させ続けるためのコントローラとして wait-controller.h と wait-controller.cpp を実装しました。これらはサブジェクトであるビューから通知を受け取るオブザーバーとして実装しています (observer.h)。</p>
<pre>
class ObserverBase : private boost::noncopyable {
public:
    virtual ~ObserverBase() = default;
    virtual void notify(int message) = 0;
};

class WatchController : public ObserverBase {
    // ...
};

class WaitController : public ObserverBase {
    // ...
};
</pre>
<p>ObserverBase クラスも SubjectBase クラスと同様、教科書通りの実装となっております。通知を受け取る純粋仮想関数 <code>notify()</code> があるだけの簡単なインタフェースです。</p>
<p>WatchController クラスは時計のリアルタイム表示処理を行います。コンストラクタに StaticText インスタンスの参照を受け取り、コンストラクタの中で初期化メッセージとインターバルタイマメッセージ用に自身を登録します。で、初期化メッセージを受け取ったタイミングで StaticText のインターバルタイマ (これは ConsoleView から継承されている機能ですね) を開始し、インターバルタイマメッセージを受け取ったタイミングで、自身がメンバに持つ DateTime オブジェクトの現在時刻更新を行いつつ、 StaticText の表示に反映させる、という仕組みです。</p>
<p>WaitController クラスはキー入力を受け取るまでひたすら待ち続けるという処理を行います。 WatchController だけだと、 インスタンスを生成したはいいけど main 関数が処理から抜けてしまってプログラムがあっという間に終わっちゃうという物悲しい現象が起こってしまうので、何もしないでただ待つだけのスレッドを用意してそれに同期 (join) することで main 関数から抜けないようにして上げる必要があり、その役目を果たすのがこのクラスというわけです。</p>
<p>作りは WatchController に割と似通っていまして、まずコンストラクタに KeyListener インスタンスの参照を受け取り、コンストラクタの中で初期化メッセージとキー入力メッセージ用に自身を登録します。で、初期化メッセージを受け取ったタイミングでコンソールに「Hit any key to finish.」などと表示しつつ、フラグが立つまでひたすら待ち続けるだけのスレッドを作って join します (このため、 <code>KeyListener::initialize()</code> メソッドの呼び出し元がブロックされる)。その直前に KeyListener が生成していたキー入力待ち受けスレッドがキー入力を受け付け、そのメッセージをこのコントローラに投げると、そこで先ほど処理をブロックするためだけに作ったスレッドを終了させるフラグを立て、めでたくブロックされていた処理が開通する、という仕組みです。</p>
<p>両方のコントローラで共通する話なのですが、ビューへのオブザーバー登録はどちらもオブザーバーであるコントローラのコンストラクタの中で行っています。 WatchController での記述を以下に示しますが、</p>
<pre>
WatchController::WatchController(StaticText &amp; text_view)
    : impl{new WatchController::Impl{text_view}}
{
    text_view.subscribe(ConsoleView::vm_Init,
        std::shared_ptr&lt;ObserverBase&gt;{this, [](ObserverBase *){}});
    text_view.subscribe(ConsoleView::vm_Timer,
        std::shared_ptr&lt;ObserverBase&gt;{this, [](ObserverBase *){}});
}
</pre>
<p><code>std::shared_ptr</code> のコンストラクタの第2引数に何もしないラムダを渡すというなんだか気持ちの悪いことをやっていますよね。何でこんなことをやっているのか。サブジェクト側ではオブザーバーインスタンスを shared_ptr でメモリー管理していますが、これはサブジェクトがどのように生成されるかわからないという前提では妥当な設計だと思うのですが、その一方で実際に登録を行うときに、これをオブザーバーのコンストラクタの中でやってしまおう、そうした方がなんだかスマートに書けそうだという場合に、 <code>this</code> ポインタをそのまま shared_ptr に包んでしまうのは非常に危険です。なぜならそのオブザーバーインスタンスはどのように生成されるかわからないし、生成した側がどのような形で管理するかもわからないので、例えばスタック変数として生成した場合や、生成した側でも unique_ptr や shared_ptr に包んで適切に破棄しようとしていた場合には、どちらかの破棄のタイミングで例外が送出される (おそらくは、アプリケーションエラーになる) ことになってしまいます。そうならないように、何もしない deleter を shared_ptr に渡し、 <code>delete</code> が呼ばれるのを防いでいるわけです。メモリーの管理責任の所在については色々と議論もあるでしょうが、私はインスタンスの生成を行った側が、そのインスタンスの破棄についても責任をもつべきだと考えています。</p>
<h4>main関数</h4>
<p>main関数はわかりやすいように main.cpp ファイルに記述しました。まず ConsoleManager インスタンスを生成し、次に日時の表示を行うビュー StaticText とコントローラ WatchController を生成して、ビューの <code>initialize()</code> メソッドを呼ぶ。同様にキー入力待受を行うビュー KeyListener とコントローラ WaitController を生成して、同じくビューの <code>initialize()</code> メソッドを呼ぶ。ただこれだけです。これだけで何でよしなに動いてくれるのか、といった辺りは、ここまでで色々と説明したとおりです… (分かんないかなぁ<tt>^^;</tt>)。</p>
<h3>作ってみた感想など</h3>
<p>前回 Pimpl をさらった時に、テキストに示されていた以外にプラットフォーム依存のコードを各状況というのがなかなか思いつかなくて try 出来なかったのですが、今回 ConsoleManager という形で <code>#ifdef</code> 書きまくることが出来たのはちょっと幸運でした。こういうのは自分で書いてみないと、他人が書いたコードを読むだけではなんだかビビってしまうばかりなので… プラットフォームごとに違うことをやるようなコードを書いて、どっちのプラットフォームでも動くのを確認するのはなかなか爽快ですよ。</p>
<p>KeyListener みたいな仕組みは、本当はビューではなく全く別の枠組みで用意すべきだったのかもしれません。 Windows のメッセージループみたいに書けるのが本当は理想的… なのかなぁ?? (よくわからん)</p>
<p>Windows の方は実際一応動くのですが、キー入力時に時々よく分からんエラーを吐いて終わることがあります (2014/8/6 時点)。何かがツメが甘いのかも…。</p>
<p>より MVC フレームワークチックにやりたいということであれば、他にも色々と改良の余地はあるんじゃないかと思います。埋め込みリソースからビューを生成とか…。</p>
<p>こちらからは以上です。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2014/08/06/observer-apides/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Boost.勉強会 #14 に行ってきました</title>
		<link>https://blog.harapeko.jp/2014/03/04/boost-study-1/</link>
		<comments>https://blog.harapeko.jp/2014/03/04/boost-study-1/#comments</comments>
		<pubDate>Tue, 04 Mar 2014 04:36:38 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[活動記録]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[講習会]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=300</guid>
		<description><![CDATA[Boost.勉強会 #14 東京 &#8211; boostjp ヲレが書いたメモ というわけで boostj [&#8230;]]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="https://sites.google.com/site/boostjp/study_meeting/study14">Boost.勉強会 #14 東京 &#8211; boostjp</a></li>
<li><a href="http://developer.harapeko.jp/trac/original/ideanote/wiki/HowTo/BoostStudy14" title="HowTo/BoostStudy14 – Idea note">ヲレが書いたメモ</a>
</ul>
<p>というわけで boostjp 書記担当(?)の @T_MURACHI でございます。ご報告遅れましたが、 3/1 に開催された Boost.勉強会 #14 に行ってきました。過去ログ見る限り #4 以来なので 3年ぶりですか…。なんかもうそろそろコンパイラ的に C++11 使えるのも当たり前になってきて当時に比べてもだいぶいい時代になったなぁとか思ってみたり (M$ 除く)。</p>
<p>内容についてはメモに書いた以上のことを語り尽くせる自信がないので、以下、感想などを思いつきで綴ってみます…。</p>
<ul>
<li>並列処理に関連する話題を取り上げた話が多かったように思います。トレンドというよりは、プロセッサなどのハードの進化の方向がもう完全にこっちに移行していっているが故の必然、といった感じなんですかね。GPGPU に関して言えば応用カテゴリはまだまだ限られている模様ですが…。</li>
<li>cpprefjp の github 連携のための涙ぐましい… という程でもないとは思うんですが^^;、Google Sites なんて使い始めちゃったのが運の尽きっちゃあ運の尽きだったのかなぁとは… でも用意されたものにうまいこと順応できるよう対応する能力ってのはこのギョーカイで仕事やってる上で絶対重宝されると思うので、そういう意味でも良い経験をされたんじゃないかなと思います。
<ul>
<li>ていうか @melponn さんかわいい。</li>
</ul>
</li>
<li>聴衆の食付きは glfw3 を使った GUI フレームワークの話が一番良かったように思います。なんだかんだ言ってみんなビジュアルグリグリ動かす系好きなんだなぁと…。 @hira_kuni_45 さん経験豊富そうで尊敬します… OpenGL 大好きで GCC 大好きで Unix ライクなのの方が好きそうなのにメインの開発環境が MinGW て… なんか某 R 社 (コピー機とか作ってる方) で働いてた時もそういう感じの方結構いらっさったような…</li>
<li>その他、グラフアルゴリズムの話とか、 C# でやってることを C++ で実装したら…の話とか、どれも非常に興味深いお話でした。面白かった。</li>
<li>会場には<a href="http://cpplover.blogspot.jp/" title="本の虫">江添さん</a>もいらっさってましたね。ドワンゴステッカー配り始めたところで確信しましたが… 思ってたよりもなんだかずっと元気なちっさいオッサンって感じでした^^;。 @cpp_akira さんと C++WG の主査がどうのこうのとかで話をしていて平行線を辿ったりとかしていたのを見るにつけ、 C++ 標準化界隈も一枚岩じゃないんだなぁとか思ってみたり…</li>
</ul>
<p>そんなこんなで、割とぶっ通しの 8時間。流石に疲れました…。参加された皆様も本当にお疲れ様でした。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2014/03/04/boost-study-1/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>C++11 で Unicode プログラミングのススメ</title>
		<link>https://blog.harapeko.jp/2011/12/27/cpp11-unicode/</link>
		<comments>https://blog.harapeko.jp/2011/12/27/cpp11-unicode/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 16:33:41 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++0x]]></category>
		<category><![CDATA[C++11]]></category>
		<category><![CDATA[Unicode]]></category>
		<category><![CDATA[wchar_t]]></category>
		<category><![CDATA[文字セット]]></category>
		<category><![CDATA[文字列処理]]></category>
		<category><![CDATA[正規表現]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=229</guid>
		<description><![CDATA[このエントリは、C++11 Advent Calendar 2011 への参加記事です。 初心者表明を免罪符に [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>このエントリは、<a href="http://atnd.org/events/21936">C++11 Advent Calendar 2011</a> への参加記事です。</p>
<p>初心者表明を免罪符にするつもりは毛頭無いのですが、 C++0x/11 の学習、およびそれを用いた経験はまだまだ浅いため、内容的に拙い部分が多々あることを、あらかじめご容赦願いたいと思います <tt>m(_ _)m</tt> 。ていうか突っ込みだいかんげいでつ。</p>
<p>一応 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf">ISO/IEC 14882:2011 の draft &#8220;n3242&#8243;</a> を参照しています。 GCC は 4.7 入れるの面倒だったので、動作確認できるものについては Ubuntu 11.10 に入っていた 4.6.1 を用いています。</p>
<h3>Unicode に対応したリテラル</h3>
<p>文字リテラルについてはドラフトの 2.14.3、文字列リテラルについては 2.14.5 に記述があります。<br />
<span id="more-229"></span><br />
文字リテラルには従来の</p>
<pre>
'a'
L'あ'
</pre>
<p>といったスタイルに加えて、</p>
<pre>
u'\u00a9'   // コピーライト記号
U'\U0002000b'  // 丈の右上に点がついた字
</pre>
<p>といったスタイルが追加されました。想定されるべき対応関係を表にすると以下の通りになります。</p>
<table>
<tr>
<th>記述スタイル</th>
<th>文字セット</th>
<th>物理型</th>
</tr>
<tr>
<td><code>'</code>&#8230;<code>'</code></td>
<td>所謂 C 文字。<br />マルチバイトの 1 オクテットでもいいし、まぁ、何でもあり。</td>
<td><code>char</code></td>
</tr>
<tr>
<td><code>l'</code>&#8230;<code>'</code> または <code>L'</code>&#8230;<code>'</code></td>
<td>ユニバーサル文字セット (UCS)。</td>
<td><code>wchar_t</code></td>
</tr>
<tr>
<td><code>u'</code>&#8230;<code>'</code></td>
<td>UTF-16</td>
<td><code>char16_t</code></td>
</tr>
<tr>
<td><code>U'</code>&#8230;<code>'</code></td>
<td>UTF-32</td>
<td><code>char32_t</code></td>
</tr>
</table>
<p>文字列リテラルではさらに <code>u8</code> という接頭子も使えます。</p>
<pre>
u8"Copyright \u00a9 2011 Harapeko, Inc."    // \u00a9 は UTF-8 のオクテット列 [C2 A9] に変換される
u"\U0002000bは「丈」の字にクリソツ"         // \U0002000b は UTF-16 の該当するサロゲートペアに変換される…ハズ
</pre>
<p>対応関係の表は、…面倒くさいからもういいか。</p>
<p>あとさらっと流しちゃいましたが、 Unicode 用のエスケープ文字も追加されました。<q><code>\uNNNN</code></q> は 16bits の、 <q><code>\UNNNNNNNN</code></q> は 32bits の UCS を表現できます。上記の例のように、適切な文字列リテラル内で使用すれば、対応する文字セットの数値列に適宜変換されるはずです。この辺の説明はドラフトの 2.3 にありますが、以下の説明の通り、あくまで UCS の文字値を表現するものであって UTF の数値列を表現するものではないので、 <code>\uNNNN</code> の形式でサロゲートペアの上位代用符号位置に相当する値を指定することはできません。</p>
<blockquote cite="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf" title="Working Draft, Standard for Programming<br />
Language C++ (N3242=11-0012)"><p>
The character designated by the universal-character-name \UNNNNNNNN is that character whose character<br />
short name in ISO/IEC 10646 is NNNNNNNN; the character designated by the universal-character-name \uNNNN<br />
is that character whose character short name in ISO/IEC 10646 is 0000NNNN. If the hexadecimal value for a<br />
universal-character-name corresponds to a surrogate code point (in the range 0xD800.0xDFFF, inclusive),<br />
the program is ill-formed. Additionally, if the hexadecimal value for a universal-character-name outside the<br />
c-char-sequence, s-char-sequence, or r-char-sequence of a character or string literal corresponds to a control<br />
character (in either of the ranges 0&#215;00.0x1F or 0x7F.0x9F, both inclusive) or to a character in the basic<br />
source character set, the program is ill-formed.15
</p></blockquote>
<h3>Unicode に対応した物理型</h3>
<p>Unicode に対応した型については、ドラフトの 3.9.1 に説明があります。重要なのは多分以下の箇所。</p>
<blockquote cite="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf" title="Working Draft, Standard for Programming<br />
Language C++ (N3242=11-0012)">
<ol start="5">
<li>Type wchar_t is a distinct type whose values can represent distinct codes for all members of the largest<br />
extended character set specified among the supported locales (22.3.1). Type wchar_t shall have the same<br />
size, signedness, and alignment requirements (3.11) as one of the other integral types, called its underlying<br />
type. Types char16_t and char32_t denote distinct types with the same size, signedness, and alignment as<br />
uint_least16_t and uint_least32_t, respectively, in &lt;stdint.h&gt;, called the underlying types.</li>
</ol>
</blockquote>
<p>エーゴは苦手なんですが、ここを読む限り、<code>wchar_t</code> はサポートするロケールに含まれるもっとも大きな値の文字値を表現できるのに十分なサイズの整数型であることが補償されてなきゃいけなさそうに見えます。 <code>wchar_t</code> については<a href="http://blog.harapeko.jp/2009/07/25/wchar_t-suck/" title="はらぺこ日誌? ブログアーカイブ ? 頼りなさげな wchar_t">大分昔に見捨てている</a>んですが <tt>(^_^;</tt> 、VC++2010 だと 32bits 整数に変更されていたりするんでしょうか…?</p>
<p># <a href="http://msdn.microsoft.com/ja-jp/library/s3f49ktz.aspx" title="Data Type Ranges (MSDN)">この辺</a>とか見る限り、やっぱり <code>unsigned short int</code> 相当、のままみたいですね… orz</p>
<p><code>char16_t</code> と <code>char32_t</code> は、それぞれ UTF-16、 UTF-32 を扱うための型と考えて差し支えなさそうです。</p>
<h3>「内部文字」のポリシー</h3>
<p>型についての想定を考えるならば、プログラムが内部で扱う文字データは、 C++11 では <code>wchar_t</code> を使用するべきであるように思われます。将来的にはそうなってゆくべきなのでしょう。しかし過去との互換性などの観点から、各ベンダーの <code>wchar_t</code> に対する取り扱いは当面現状維持か、もしくは段階的な仕様変更 (コンパイラオプションでの切り替え等) となっていくことが予想されます。</p>
<p>それに対し、 UTF-32 に関して言えば、恐らく向こう十何年かぐらいは「1要素 = UCS 1文字」であり続けるのではないかと思われます。従って、内部文字への要件として「1文字を 1つの数値のみで扱いたい」というのがあるのであれば、当面は <code>char32_t</code> と <code>U"</code>&#8230;<code>"</code> 形式のリテラルを用いるのが良さそうです。</p>
<table>
<tr>
<th>要件</th>
<th>選択すべき型と文字セット</th>
</tr>
<tr>
<td>
<ul>
<li>1文字を 1つの数値のみで扱いたい</li>
<li>メモリー使用量は気にしないか、32bits 幅でも十分管理可能</li>
</ul>
</td>
<td><code>char32_t</code>、 UTF-32</td>
</tr>
<tr>
<td>
<ul>
<li><code>&lt;</code>(<code>boost/</code>)<code>regex&gt;</code> を使いたい (後述)</li>
<li>UTF-8 のクセに精通しているのでマルチバイトでも気にならない</li>
<li>メモリー使用量を極力抑えたい</li>
</ul>
</td>
<td><code>char</code>、 UTF-8</td>
</tr>
<tr>
<td>
<ul>
<li>とにかく <code>wchar_t</code> を使い慣れている</li>
<li>数十年後の未来との互換性、汎用性に賭けたい</li>
</ul>
</td>
<td><code>wchar_t</code>、 UCS</td>
</tr>
</table>
<h3>char32_t で文字列置換を試してみる</h3>
<p>そんなわけで、実際に UTF-32 を内部文字の文字セットとして採用したプログラム例を作ってみることにしました。内容的には、静的に用意した文字列内のすべての「くま」を「ぱんだ」に置き換える、という簡単なものです。</p>
<pre>
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;

using namespace std;

int main()
{
    u32string before = U&quot;てくまくまやこんてくまくまやこん むらやましゃちょうよ おおきなくまにな～ぁれ&quot;;
    u32string after;
    u32string kuma = U&quot;くま&quot;;
    u32string panda = U&quot;ぱんだ&quot;;

    auto start_it = before.begin();
    auto find_it = start_it + (kuma.size() - 1);
    while (find_it &lt; before.end()) {
        int cnt = 0;
        auto stop_it = find_if(kuma.rbegin(), kuma.rend(), [&amp;cnt, find_it](char32_t letter) {
            return *(find_it - cnt++) != letter;
        });
        if (stop_it != kuma.rend()) {
            find_it += cnt;
            continue;
        }
        // くまを発見、ぱんだに変身!!
        after.append(start_it, find_it - (kuma.size() - 1));
        after += panda;
        start_it = find_it + 1;
        find_it = start_it + (kuma.size() - 1);
    }
    after.append(start_it, find_it);

    cout &lt;&lt; &quot;before: &quot; &lt;&lt; before.size() &lt;&lt; endl;
    cout &lt;&lt; &quot;after: &quot; &lt;&lt; after.size() &lt;&lt; endl;

    return 0;
}
</pre>
<p>えっと… アルゴリズムの説明とかはいいですよね? 文字列の先頭からと検索語の後からで評価して、完全一致しなかった場合は一致した数値の数だけ読み飛ばして、を繰り返すというオーソドックスなやり方です。これだったらかっこつけて <code>find_if</code> とか使わんで <code>for</code> で回しても大して変わらんやんとかそういう突っ込みはさておき <tt>(^_^;</tt> 。</p>
<p>GCC4.6/Ubuntu での実行結果は以下の通り。</p>
<pre>
murachi@ubuntu-vbox:~/otoco/trunk/sample$ g++ -std=c++0x -o kumapan-n kumapan-n.cpp 
murachi@ubuntu-vbox:~/otoco/trunk/sample$ ./kumapan-n
before: 39
after: 44
murachi@ubuntu-vbox:~/otoco/trunk/sample$ 
</pre>
<p>実行結果として置換前後の <code>u32string::size()</code> を表示しています。 5つある「くま」が「ぱんだ」に置き換えられたので、その数が 5 増えています。増える筈の文字数と一致するので、正しく動作しているように見えます。</p>
<h3>iconv を使って実際に出力してみる</h3>
<p>さて、実際の文字列を出力してみたいのですが、このままだとロケールが UTF-8 で動作している端末上では表示できません。ファイルに出力してテキストエディタで、という手もありますが、せっかくなので libiconv を使って指定した文字セットに変換して出力、ということをやってみることにしましょう。</p>
<p>libiconv の利用に際しては、お手製のラッパークラスを作成することで対応しました。作成したソースコードを以下にリンクします。</p>
<ul>
<li><a href="http://developer.harapeko.jp/trac/original/otoco/browser/trunk/sample/EncodeString.hpp?rev=16">EncodeString.hpp</a></li>
<li><a href="http://developer.harapeko.jp/trac/original/otoco/browser/trunk/sample/EncodeString.cpp?rev=16">EncodeString.cpp</a></li>
</ul>
<p>このクラスは<a href="http://blog.harapeko.jp/2010/09/22/utf-8-is-nice/" title="はらぺこ日誌? ブログアーカイブ ? UTF-8 もイマイチだが…">過去の記事</a>においても使用しておりますが、 C++11 の勉強も兼ねて (?)、内部文字に使用する物理型と文字セットをテンプレートパラメータに指定できるテンプレートクラスに書き換えています (あ、過去の記事でのソースへのリンク先が最新版になっちゃってる…直さなきゃ…)。</p>
<p>そして先ほどのサンプルプログラムは、最初の方で <code>EncodeString.hpp</code> を <code>#include</code> し、</p>
<pre>
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;

#include &quot;EncodeString.hpp&quot; // ←

using namespace std;
</pre>
<p>最後の方で出力内容を以下のように修正します。</p>
<pre>
    cout &lt;&lt; &quot;before: &quot; &lt;&lt; EncodeString&lt;char32_t, chset_Utf32&gt;(before, chset_Utf8).getCharArray() &lt;&lt; endl;
    cout &lt;&lt; &quot;after: &quot; &lt;&lt; EncodeString&lt;char32_t, chset_Utf32&gt;(after, chset_Utf8).getCharArray() &lt;&lt; endl;
</pre>
<p>Windows 環境とかで Shift JIS (CP-932) で出力したい人は、 <code>chset_Utf8</code> を <code>chset_Cp932</code> に置き換えてあげれば ok です。GCC4.6/Ubuntu での実行結果は以下の通り。</p>
<pre>
murachi@ubuntu-vbox:~/otoco/trunk/sample$ g++ -std=c++0x -o kumapan EncodeString.cpp kumapan.cpp 
murachi@ubuntu-vbox:~/otoco/trunk/sample$ ./kumapan
before: てくまくまやこんてくまくまやこん むらやましゃちょうよ おおきなくまにな～ぁれ
after: てぱんだぱんだやこんてぱんだぱんだやこん むらやましゃちょうよ おおきなぱんだにな～ぁれ
murachi@ubuntu-vbox:~/otoco/trunk/sample$ 
</pre>
<p>環境によっては libiconv を別途導入してコンパイルオプションに <code>-liconv</code> を付け加える必要があるかもしれません (MinGW とか←動作未確認)。</p>
<h3>正規表現を使いたい</h3>
<p>さて、上記のサンプルでさらっと <code>u32string</code> とか使っちゃってますが、このシノニムはドラフトの 21.3 にてちゃんと明記された標準のものです。もちろん、 <code>u16string</code> というのも存在します (<code>u8string</code> は無いので、考慮されているのはアラインメントのみと考えるべきですが…)。</p>
<p>しかし、「28 Regular expressions library」の章においては、 <code>char32_t</code> という文字はカケラも hit しません。標準の <code>&lt;regex&gt;</code> においては、 <code>char16_t</code>、 <code>char32_t</code> への対応は見送られてしまっているようです。</p>
<p>もちろん、<code>basic_regex</code> はテンプレートクラスなのですから、自分でテンプレートパラメータを指定してあげればうまくいきそうに見えます。しかし、<a href="http://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/" title="はらぺこ日誌? ブログアーカイブ ? char32_t だと regex が使えない">同様の試みを Boost.Regex について行った際には、 <code>std::bad_cast</code> 例外が送出されてプログラムがエラー終了してしまいました</a>。将来的には、あるいは処理系によってはうまく動かせる (ようになる) のかもしれませんが、あまり期待は持たない方が良いかもしれません…。</p>
<p># そもそも <a href="http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.200x" title="C++ 200x - Chapter 1. Status (libstdc++)">GCC (libstdc++) では <code>&lt;regex&gt;</code> 自体がまだちゃんと実装されてなかったり</a>… orz</p>
<p>もっとも、<a href="http://blog.harapeko.jp/2011/09/21/boostregex-icu-with-char32_t/" title="はらぺこ日誌? ブログアーカイブ ? Boost.Regex の ICU 拡張と char32_t は相性がいいかも?">Boost.Regex の ICU 拡張における <code>UChar32</code> と <code>char32_t</code> (およびそれらの配列へのポインタ) を無理矢理キャストして使うと割と上手く行くっぽかったりする</a>ので、どうにかこうにかラッパーを書いて当座はそれで凌ぐというのも手かもしれません…。</p>
<p>ちなみに、<code>char</code> と UTF-8 を使用するのであれば <code>&lt;regex&gt;</code> はそのまま使えるはずですが、その場合、 (Boost.Regex と同様に) <a href="http://blog.harapeko.jp/2010/09/22/utf-8-is-nice/" title="はらぺこ日誌? ブログアーカイブ ? UTF-8 もイマイチだが…"><code>&lt;regex&gt;</code> は UTF-8 を知らないので、マルチバイト特有の問題に悩まされることになる</a>でしょう。少なくとも日本語の文字に対する量指定子 (<q><code>あ+</code></q> とか <q><code>あ?</code></q> とか) は期待通りには動きません。</p>
<p>仮に、<code>&lt;regex&gt;</code> が <code>char32_t</code> で利用できる場合、先のサンプルは以下のようなコーディングになるでしょう。こういう風に組める日がいつか来るといいですね… <tt>(;_;)/</tt>。</p>
<pre>
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
#include &lt;regex&gt;

#include &quot;EncodeString.hpp&quot;

using namespace std;

typedef basic_regex&lt;char32_t, regex_traits&lt;char32_t&gt;&gt; u32regex;
typedef match_results&lt;u32string::const_iterator&gt; u32smatch;


int main()
{
    u32string before = U&quot;てくまくまやこんてくまくまやこん むらやましゃちょうよ おおきなくまにな～ぁれ&quot;;
    u32string after;
    u32regex reg(U&quot;くま&quot;);
    u32smatch match;

    u32string textbuf = before;
    while (regex_search(textbuf, match, reg)) {
        after += match.prefix().str() + U&quot;ぱんだ&quot;;
        textbuf = match.suffix().str();
    }
    after += textbuf;

    cout &lt;&lt; &quot;before: &quot; &lt;&lt; EncodeString&lt;char32_t, chset_Utf32&gt;(before, chset_Utf8).getCharArray() &lt;&lt; endl;
    cout &lt;&lt; &quot;after: &quot; &lt;&lt; EncodeString&lt;char32_t, chset_Utf32&gt;(after, chset_Utf8).getCharArray() &lt;&lt; endl;

    return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2011/12/27/cpp11-unicode/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Boost.Regex の ICU 拡張と char32_t は相性がいいかも?</title>
		<link>https://blog.harapeko.jp/2011/09/21/boostregex-icu-with-char32_t/</link>
		<comments>https://blog.harapeko.jp/2011/09/21/boostregex-icu-with-char32_t/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 02:27:05 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++0x]]></category>
		<category><![CDATA[Unicode]]></category>
		<category><![CDATA[文字列処理]]></category>
		<category><![CDATA[正規表現]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=205</guid>
		<description><![CDATA[なんとなく Virtual Box から利用している Ubuntu のアップグレードなどをして、そこからなんと [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>なんとなく Virtual Box から利用している Ubuntu のアップグレードなどをして、そこからなんとなく「やっぱり Long Time Release 版の Ubuntu もテスト環境に持っておきたいよなぁ」などと思いつつ Virtual Box ディスクイメージを追加でこさえて、 Boost ライブラリのセットアップなどもしつつ動作チェックも兼ねて<a href="http://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/" title="はらぺこ日誌» ブログアーカイブ » char32_t だと regex が使えない">昔書いた記事</a>なんぞを掘り起こしておりましたら、そこに書かれた内容に関連して、そういえば Boost.Regex も ICU ライブラリと組み合わせれば Unicode に対応できたはずだよなぁなどということが気になりだしてしまいまして、いろいろ試しているうちに、以下のようなサンプルコードが問題なく動作してしまうことを発見してしまったのでメモしておこうかと思った次第なのであります。ああ、なんだかこちらのブログも口調が個人ブログや普段の Twitter とかでのそれに似てきてしまいました <tt>(^_^;A</tt> 。<br />
<span id="more-205"></span></p>
<pre>
#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;boost/regex.hpp&gt;
#include &lt;boost/regex/icu.hpp&gt;

using namespace std;

using boost::u32regex;
using boost::u32match;

int main()
{
        u32string text(U&quot;C++0x のせかいへようこそ!!&quot;);
        cout &lt;&lt; &quot;pre-modified text length = &quot; &lt;&lt; text.length() &lt;&lt; endl;
        u32string modified;
        u32regex reg(reinterpret_cast&lt;UChar32 const*&gt;(U&quot;せかい&quot;));
        u32match match;
        while (boost::regex_search(reinterpret_cast&lt;UChar32 const*&gt;(text.c_str()), match, reg)) {
                modified += u32string(reinterpret_cast&lt;char32_t const*&gt;(match.prefix().str().c_str())) + U&quot;世界&quot;;
                text = reinterpret_cast&lt;char32_t const*&gt;(match.suffix().str().c_str());
        }
        modified += text;
        cout &lt;&lt; &quot;modified text length = &quot; &lt;&lt; modified.length() &lt;&lt; endl;
        return 0;
}
</pre>
<p>とりあえず動作確認環境は以下の通りです。</p>
<ul>
<li>Ubuntu 11.04 + gcc 4.5.2 + Boost 1.42.0</li>
<li>Ubuntu 10.04 LTS + gcc 4.4.3 + Boost 1.40.0</li>
</ul>
<p>どちらでもコンパイルコマンドは以下で通ります (ソースファイルを <code>u32test.cpp</code> として保存した場合)。</p>
<pre>
$ g++ -std=c++0x -o u32test u32test.cpp -lboost_regex
</pre>
<p>実行してみると、置換前と置換後の文字数が正しくカウントされており、マッチングが期待通りに動作していることが確認できます。</p>
<pre>
$ ./u32test
pre-modified text length = 17
modified text length = 16
$ 
</pre>
<p>ただ、コードを見ていただければわかる通り、 <code>reinterpret_cast</code> の嵐であり、こうした書き方が C++0x 的にも Boost.Regex 的にも ICU 的にも Valid なのかはわかりません。また、現時点では Windows 環境 (MinGW + gcc 4.5 など) での動作確認は行っておりません。 ICU 拡張部分のヘッダを見る限り、内部で <code>wchar_t</code> を使っているので、 <code>wchar_t</code> が 16bits 境界になっている Windows では、バイトオーダーがひっくり返るなどの問題があって、もしかしたら正常に動かないかもしれません。</p>
<p>あくまで参考までと言いますか、将来的にはこういう感じの書き方ができるようになると良いなぁと言う程度の妄想、と捉えていただければと思います… <tt>m(_ _)m</tt></p>
<p>ちなみに、ここ最近ちっとも進んでいない otoco ですが、恐らく C++0x 自体の採用を見送る形になると思われます…。ただ、 Boost.Regex の ICU 拡張は有効利用できそうな気がしてきたので、こちらは利用することになるかもしれません。</p>
<p>Google の <a href="http://code.google.com/p/re2/">re2</a> に流れてしまいそうな悪寒もしてますが…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2011/09/21/boostregex-icu-with-char32_t/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Boost.勉強会 #4 に行ってきました。</title>
		<link>https://blog.harapeko.jp/2011/02/26/boost%e5%8b%89%e5%bc%b7%e4%bc%9a-4-%e3%81%ab%e8%a1%8c%e3%81%a3%e3%81%a6%e3%81%8d%e3%81%be%e3%81%97%e3%81%9f%e3%80%82/</link>
		<comments>https://blog.harapeko.jp/2011/02/26/boost%e5%8b%89%e5%bc%b7%e4%bc%9a-4-%e3%81%ab%e8%a1%8c%e3%81%a3%e3%81%a6%e3%81%8d%e3%81%be%e3%81%97%e3%81%9f%e3%80%82/#comments</comments>
		<pubDate>Sat, 26 Feb 2011 11:43:20 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++0x]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=154</guid>
		<description><![CDATA[Boost.勉強会 #4 : ATND 前回 今回も必死こいてメモ執りましたよ。終盤力尽きたけど orz Bo [&#8230;]]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://atnd.org/events/11551">Boost.勉強会 #4 : ATND</a></li>
<li><a href="http://blog.harapeko.jp/2010/09/12/boost-study/">前回</a></li>
</ul>
<p>今回も必死こいてメモ執りましたよ。終盤力尽きたけど orz</p>
<ul>
<li><a href="http://developer.harapeko.jp/trac/original/ideanote/wiki/HowTo/BoostStudy4">Boost.勉強会 #4 ノート</a></li>
</ul>
<p>しかしさすがにこの年で一日通しはキツいっすなぁ…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2011/02/26/boost%e5%8b%89%e5%bc%b7%e4%bc%9a-4-%e3%81%ab%e8%a1%8c%e3%81%a3%e3%81%a6%e3%81%8d%e3%81%be%e3%81%97%e3%81%9f%e3%80%82/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UTF-8 もイマイチだが…</title>
		<link>https://blog.harapeko.jp/2010/09/22/utf-8-is-nice/</link>
		<comments>https://blog.harapeko.jp/2010/09/22/utf-8-is-nice/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 14:55:16 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++0x]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[Unicode]]></category>
		<category><![CDATA[文字列処理]]></category>
		<category><![CDATA[正規表現]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=138</guid>
		<description><![CDATA[UTF-32 が内部文字列に使えないことがわかったので、 UTF-8 を内部文字列に使用するというルールで l [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/" title="はらぺこ日誌» ブログアーカイブ » char32_t だと regex が使えない">UTF-32 が内部文字列に使えないことがわかった</a>ので、 UTF-8 を内部文字列に使用するというルールで libiconv によるエンコーディング操作と Boost.Regex による正規表現の両方を同時に試すサンプルを作成してみました。</p>
<ul>
<li><a href="http://developer.harapeko.jp/trac/original/otoco/browser/trunk/sample/EncodeString.hpp">sample/EncodeString.hpp</a></li>
<li><a href="http://developer.harapeko.jp/trac/original/otoco/browser/trunk/sample/EncodeString.cpp">sample/EncodeString.cpp</a></li>
<li><a href="http://developer.harapeko.jp/trac/original/otoco/browser/trunk/sample/regex-test.cpp">sample/regex-test.cpp</a></li>
</ul>
<p>Makefile は作ってません＼(^O^)／。試してみたい人は頑張ってコンパイルしてねｗ</p>
<pre>
$ g++ -std=c++0x -o regex-test regex-test.cpp EncodeString.cpp -lboost_regex
</pre>
<p>まともな環境 (Linux + GCC4.5 とか) なら上記コマンドで通るはず。libiconv を (glibc に上書きする形で) インストールしている場合は <code>-liconv</code> を末尾に入れる必要があるかも。そして MinGW を使う場合は更にもう一工夫必要かも <tt>(((;/^^)/</tt><br />
<span id="more-138"></span><br />
さてこのプログラム、注目して頂きたいのは、<code>regex-test.cpp</code> の以下の行です。</p>
<pre>
        regex reg(u8"くま|川|(お)?魚");
</pre>
<p>正規表現を定義しているのですが、一文字でしかないはずの <code>"お"</code> がわざわざ丸括弧でくくってありますね。これが Perl で <code>use utf8;</code> していたり、 UTF-8 で JavaScript を書いていたりしているのであれば、不要な括弧です。</p>
<p>しかし、 Boost.Regex を UTF-8 で使用する場合には必要です。この括弧がなければ、 <code>"?"</code> は <code>"お"</code> の最終オクテットにしか適用されません。なぜなら、 Boost.Regex は UTF-8 なんて知らないので、 <code>"お"</code> が論理的には 1文字でしかない、なんてことは認識できないからです。</p>
<p>すなわち、</p>
<pre>
        regex reg(u8"くま|川|お?魚");
</pre>
<p>と書いてしまうと、<code>"お魚"</code> には hit しますが、 <code>"魚"</code> には hit しなくなってしまうのです。</p>
<p>otoco では、 MML コンパイラ機能において、プログラマブルマクロを定義できる機能を提供する予定です。具体的には Lua でマクロを定義し、そのマクロを用いて生成した MML をインライン展開できるようにする、といったものです (実際の所、言語に Lua を採用すべきか JavaScript を採用すべきか、はたまた Python を採用すべきかで迷っているところではあるのですが…)。</p>
<p>で、 (Lua を採用する場合には) 正規表現を用いた文字列加工を行う関数を提供するつもりでいるのですが (JavaScript とかだったら不要なんですけどね、言語機能にあるし)、仮に非 ASCII な文字 (列) を hit させようとする正規表現に <code>"?"</code> やら <code>"[</code>…<code>]"</code> やらが使われた場合、どう扱うべきなんだろう、といった辺りが悩みどころではあったりします…。</p>
<p>まぁなんにせよ、他に選択の余地もないので、とりあえず内部文字列は UTF-8 で実装するという方針でやっていくことにしようかと思います。前途多難じゃ… orz</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2010/09/22/utf-8-is-nice/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>char32_t だと regex が使えない</title>
		<link>https://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/</link>
		<comments>https://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/#comments</comments>
		<pubDate>Wed, 22 Sep 2010 02:21:44 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++0x]]></category>
		<category><![CDATA[GCC]]></category>
		<category><![CDATA[iconv]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[Unicode]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=133</guid>
		<description><![CDATA[C++0x では UCS に対応し、専用の型やリテラルの記法が導入されました。その関係で、以下の点について調査 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>C++0x では UCS に対応し、<a href="http://ja.wikipedia.org/wiki/C%2B%2B0x#.E6.96.B0.E3.81.9F.E3.81.AA.E6.96.87.E5.AD.97.E5.88.97.E3.83.AA.E3.83.86.E3.83.A9.E3.83.AB" title="新たな文字列リテラル - C++0x - Wikipedia">専用の型やリテラルの記法が導入されました</a>。その関係で、以下の点について調査を行っていました。</p>
<ol>
<li>C++0x で UCS を UTF-32 として扱う型 <code>char32_t</code>, <code>u32string</code> およびリテラル <code>U"..."</code> と、 libiconv の UCS-4-INTERNAL との間に互換性はあるか。</li>
<li>C++0x で新たに追加された正規表現ライブラリ <code>&lt;regex&gt;</code> は利用可能か。</li>
<li><code>&lt;regex&gt;</code> が利用できない場合、 Boost.Regex を用いて UTF-32 文字列を処理することは可能か。</li>
</ol>
<p>これらの調査は、すべて otoco のコアデータを扱うプログラム内で内部文字列に UTF-32 を採用することを前提としたものでした。<br />
<span id="more-133"></span><br />
結論から言うと、<strong>内部文字列に UTF-32 を採用することは、現時点では諦めざるを得ない、ということになりました。＼(^O^)／</strong> 以下、その解説です。</p>
<p>1 については、互換性に問題がないことを確認しました。</p>
<p>2 についてですが、 GCC 4.5 の標準 C++ ライブラリでは、 <code>&lt;regex&gt;</code> のヘッダファイルは存在するものの、ライブラリの実体がまだ用意されていない、という状態のようでした。</p>
<p>で、 3 についてなのですが… 簡単のため、以下のサンプルを見てみることにします。</p>
<pre>
#include &lt;string&gt;
#include &lt;boost/regex.hpp&gt;

using namespace std;

typedef boost::basic_regex&lt;char32_t, boost::regex_traits&lt;char32_t&gt; &gt; u32regex;
typedef boost::match_results&lt;u32string::const_iterator&gt; u32smatch;

int main()
{
	u32string text(U&quot;C++0x のせかいへようこそ!!&quot;);
	u32string modified;
	u32regex reg(U&quot;せかい&quot;);
	u32smatch match;
	while (boost::regex_search(text, match, reg)) {
		modified += match.prefix().str() + U&quot;世界&quot;;
		text = match.suffix().str();
	}
	modified += text;
	return 0;
}
</pre>
<p>このサンプルは、期待通りに動作しても、何もしません。UTF-32 の文字列 <code>U"C++0x のせかいへようこそ!!"</code> の <code>U"せかい"</code> を <code>U"世界"</code> に置換する、という処理を内部で行うだけです。 <code>u32string</code> に対応した <code>iostream</code> があったとして、 UTF-32 をそのままコンソールやファイルに出しても不親切なだけなので、出力までやるなら libiconv と組み合わせるべきですが、プログラムが複雑になるので、ここではそこまで示していません (実際にはそこまで試そうとしていたのですが…)。</p>
<p>で、このプログラム、実際はどうなるのかというと、 GCC 4.5 でコンパイルは通るものの、実行すると、 <strong><code>u32regex</code> オブジェクト</strong> (これは <code>boost::basic_regex&lt;char32_t, boost::regex_traits&lt;char32_t&gt; &gt;</code> のシノニムですね) <strong>のコンストラクタが <code>std::bad_cast</code> 例外を送出します</strong>。どうやら、 Boost.Regex は <code>char32_t</code>、すなわち 32bits 以上の整数型を文字コードに使用するということ、を想定した作りにはなっていなかったようなのです。よーするに <code>char</code> と <code>wchar_t</code> しか想定していなかったんですね (ん? でも <a href="http://blog.harapeko.jp/2009/07/25/wchar_t-suck/" title="はらぺこ日誌» ブログアーカイブ » 頼りなさげな wchar_t">GCC の <code>wchar_t</code> は <code>uint32_t</code></a> だったような…)。</p>
<p>GCC の標準 C++ ライブラリが <code>&lt;regex&gt;</code> のライブラリを実装するのを悠長に待っても居られないので、方針を転換し、内部文字列は UTF-8 で実装せざるを得なさそうです。一応、UTF-8 は文字の先頭オクテットか否かを判断するのが容易なので (0&#215;80≦n≦0xBF 以外なら先頭オクテット)、文字境界の特定も文字数カウントも一度関数を書いてしまえば ok なのですが…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2010/09/22/u32regex-bad-cast/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Boost.勉強会 #2 に参加しました。</title>
		<link>https://blog.harapeko.jp/2010/09/12/boost-study/</link>
		<comments>https://blog.harapeko.jp/2010/09/12/boost-study/#comments</comments>
		<pubDate>Sun, 12 Sep 2010 03:47:18 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[C++0x]]></category>
		<category><![CDATA[講習会]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=130</guid>
		<description><![CDATA[Boost.勉強会 #2 : ATND 実に楽しいイベントでした。 5時間ほぼぶっ通しだったのでさすがにくたび [&#8230;]]]></description>
				<content:encoded><![CDATA[<ul>
<li><a href="http://atnd.org/events/7148">Boost.勉強会 #2 : ATND</a></li>
</ul>
<p>実に楽しいイベントでした。 5時間ほぼぶっ通しだったのでさすがにくたびれましたが… (^_^;A</p>
<p><a href="http://developer.harapeko.jp/trac/original/ideanote/wiki/HowTo/BoostStudy2" title="Boost.勉強会 #2 ノート – Idea note">自分なりにメモしたノートを公開しています</a>ので、よかったら復習にご活用ください。かなり荒いメモですが…。<br />
<span id="more-130"></span><br />
そういえば sexyhook2 の話で Win32 API をフックするのに DLL を読み込んだプログラム領域を直接書き換えているんだけどそれって大丈夫なんだっけ? という話題が出て、昔、 3D CAD モックアップツールのプロセスを生成してからデバッグアタッチし、そのプロセスが読み込んでいる <a href="http://msdn.microsoft.com/en-us/library/dd369060%28v=VS.85%29.aspx">SwapBuffers()</a> API や <a href="http://msdn.microsoft.com/en-us/library/dd374391%28v=VS.85%29.aspx">wglSwapLayerBuffers()</a> API の先頭アドレスをブレークポイント命令に置き換えて、 <a href="http://msdn.microsoft.com/ja-jp/library/cc429065.aspx">WaitForDebugEvent()</a> API がブレークポイントを拾ってくる時間あたりの回数をカウントすることで、そのモックアップツールの 3D 処理をベンチマークするツールを (仕事で!) 作ったことがあるおいらとしては、そのときは「まぁ、大丈夫なんでねぇの?」とか思いつつ特に何もコメントしなかったのですが、後になってなんとなーく、そういえば<strong>その辺の扱いって NT 系と 9x 系とでは違ってたよーな</strong>…とか思い返したりしたわけですが、はっきり言ってうろ覚えなのでなんとも言えんのです。一応調べて rti さんに伝えておいた方がいいかな…そもそも 9x 系に対応するのかどうかは別として。</p>
<p>しかしこの手の講習会は当方初参戦だったのですが、とても刺激になります。周り若い人ばっかりだし…。今後もいろいろと参加したいです。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2010/09/12/boost-study/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>久しぶりに…</title>
		<link>https://blog.harapeko.jp/2009/09/09/recovery/</link>
		<comments>https://blog.harapeko.jp/2009/09/09/recovery/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 22:25:56 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[活動記録]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[otoco]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=105</guid>
		<description><![CDATA[Boost セットアップ中… orz 実は先日 HDD に物理的損傷らしきものを見つけてしまいまして、必要なデ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><strong>Boost セットアップ中… orz</strong></p>
<p>実は先日 HDD に物理的損傷らしきものを見つけてしまいまして、必要なデータだけ抜き取ってフォーマットを試みたら見事にエラーで止まりやがったのでやむなく新しいのに交換したのですよ。</p>
<p>ここ最近は忙しかったり体調も安定しなかったりだったので otoco の方の作業はずっと停滞してました…。やっと朝まともに起きれるぐらいに体調は戻ってきたので、そろそろ otoco の作業も復活したいなぁと思いつつ…。</p>
<p>ああそうだ、Linux も使えるように grub 入れ直さないと…。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2009/09/09/recovery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu への Boost セットアップとバージョン間差異の問題</title>
		<link>https://blog.harapeko.jp/2009/07/23/boost-setup-for-ubuntu-and-differ-by-version/</link>
		<comments>https://blog.harapeko.jp/2009/07/23/boost-setup-for-ubuntu-and-differ-by-version/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 23:18:38 +0000</pubDate>
		<dc:creator><![CDATA[村山 俊之]]></dc:creator>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[活動記録]]></category>
		<category><![CDATA[Boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[otoco]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://blog.harapeko.jp/?p=93</guid>
		<description><![CDATA[Boost ライブラリの Ubuntu へのインストールは容易でした。単に libboost-dev パッケー [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Boost ライブラリの Ubuntu へのインストールは容易でした。単に libboost-dev パッケージを <code>aptitude install</code> してあげるだけです。</p>
<p>問題は、<a href="http://blog.harapeko.jp/2009/07/16/boost-setup-investigation/">前回も書いた通り</a>、 apt からインストールできる Boost のバージョンは通常で 1.34.1、最新のものを選んでも 1.37.0 になってしまう、ということです。</p>
<p>そこで、 otoco の開発に影響する範囲で、バージョン間にどの程度の差異があるのか、調べておくことにしました。</p>
<ul>
<li><a href="http://developer.harapeko.jp/trac/original/otoco/wiki/%E6%8A%80%E8%A1%93%E3%83%A1%E3%83%A2/Boost%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3">Boost ライブラリ &#8211; バージョン間の差意について</a></li>
</ul>
<p>とりあえず今思いつくのは正規表現まわりだけだったのでまだそこしか調べていないのですが (空文字列マッチは何気に影響範囲大きそうですが…古いバージョンで統一しておけばとりあえず問題にはならないかな…)、実際に開発が進めば利用範囲が広がり、都度気づく部分も増えていくかもしれません。上記ページはその都度更新して行く予定です。</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.harapeko.jp/2009/07/23/boost-setup-for-ubuntu-and-differ-by-version/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
