2010-11-18-01-文字コードの話 - 16
>> Site top >> weblog >> 月別アーカイブ >> 2010年11月のlog >> 2010-11-18-01-文字コードの話 - 16
最終更新日付:2010/11/18 01:00:00
文字コードの話 - 16
2010 年 11 月 18 日
今回は、関数テンプレートに反復子が渡された場合の利便性について。
まずは以下の関数テンプレートから始めよう。反復子の型をテンプレートパラメータに、そして反復子そのものをパラメータにとっている。
template<typename ITR> int DoSomething( ITR itr ) { // do something... }
そして、上記の関数テンプレートを利用するコードはこんな感じだ。
UTF8::ConstIterator itr = utf8.GetConstIterator( p ); int ret = DoSomething( itr );
さて、この DoSomething の中で反復子だけでなくエンコーディングクラスも使いたくなったとしよう。ひとまず考えられるのは、テンプレートパラメータを変えることだ。以下のように。
template<typename ENC> int DoSomething( typename ENC::ConstIterator itr ) { const ENC& enc = ENC::handler; // do something... }
これはエンコーディングクラスの型をテンプレートパラメータにとり、実パラメータはその ConstIterator をとる。これで、内部で ENC::handler にアクセスできる。これはこれで問題ないように見える。
しかし、残念ながらこれは上手く行かない。というか良くない。なぜなら、Dynamic クラスに対応できていないからだ。動的解決のための Encoding::Dynamic は静的メンバ handler を持っていない。これに対応するひとまずの方法は、パラメータとして渡すことだ。そしてエンコーディングクラスのオブジェクトは呼び出し元が用意する。これで Dynamic にも対応できるはずだ。
template<typename ENC> int DoSomething( const ENC& enc, typename ENC::ConstIterator itr ) { // do something... }
なんだかごちゃごちゃしてきた。そして、これまたダメなのである。ダメというか、動くけどイマイチなのだ。なぜなら、以下のような呼び出しをガードできないからだ。
const Dynamic& enc1 = Dynamic.GetEncoding( TYPE_UTF8 ); const Dynamic& enc2 = Dynamic.GetEncoding( TYPE_SJIS ); Dynamic::ConstIterator itr = enc1.GetConstIterator( p ); int ret = DoSomething( enc2, itr );
もちろんわざとらしいコードだ。とにかく、Dynamic では反復子のそれと異なるエン コーディングオブジェクトを(その気になれば)渡せてしまう。わざとやることはまぁ ないとしても、こういうことがミスや事故で発生しないようなデザインにすることが重 要だ。
最後の問題は、Dynamic クラスを考慮に入れる場合、エンコーディングオブジェクトと反復子を別で渡すべきではないということを意味している。これを解決するには、反復子からエンコーディングクラスの型とオブジェクトを取得可能にすることだ。
これを実現するために、エンコーディングクラスに EncodingType という typedef とGetEncoding というメソッドを追加する。以下のような感じだ。
class UTF8::Iterator { public: typedef UTF8 EncodingType; public: const EncodingType& GetEncoding( ) const; : : };
こうすることにより、反復子の型だけをテンプレートパラメータとしてとる最初のかたちでも内部でエンコーディングオブジェクトを利用できるようになる。
template<typename ITR> int DoSomething( ITR itr ) { const typename ITR::EncocingType& enc = itr.GetEncoding( ); // do something... }
今回のこの変更は、ある程度の規模のコードで実際にエンコーディングクラスとその反復子を使ってみて発生した要件だ。3つも4つも向こうの呼び出し先でエンコーディングクラスを利用するために反復子とセットで渡していくのに違和感と問題を感じたことから始まっている。まだ対応作業は続いているので、ひょっとしたらまた新たな変更が発生するかもしれない。その時にはまた続きを書くことになるが、ひとまずはこれでお開きにしよう。
コメント
このページのタグ
Page tag : 開発
Copyright(C) 2005-2021 project-enigma.
Generated by CL-PREFAB.