« テンプレートでバイナリ増大中 | メイン | HTMLをSubversionで管理しながらWebで参照可能に »

2008年01月01日

日常の備忘録:: テンプレートと多重定義された関数のポインタ

    

オーバーロードされたメンバ関数の関数ポインタを取得してテンプレートで定義された関数に渡そうとしたらうまく行かなかった。
解決方法がわかったのでメモしておく。
まず定義されていた関数は以下の通り。

template<typename sr_t, typename sc_t, typename prop_t, typename gc_t >
inline CPropertyLoader<std::mem_fun1_t<sr_t,sc_t,prop_t>,std::const_mem_fun_t<prop_t,gc_t> >*
 createLoader( sr_t (sc_t::*pms)(prop_t), prop_t (gc_t::*pmg)() const )
{
  return new CPropertyLoader<std::mem_fun1_t<sr_t,sc_t,prop_t>,std::const_mem_fun_t<prop_t,gc_t> >(
    new std::mem_fun1_t<sr_t,sc_t,prop_t>(pms),
    new std::const_mem_fun_t<prop_t,gc_t>(pmg) );
}

対象としていたクラスの一部は以下の通り。

class CSpriteBase
{
public:
  void SetVisible( int frame, bool visible );
  void SetVisible( bool visible );
  bool IsVisible() const;
};

この時、以下のように記述すると void SetVisible( int frame, bool visible ) のポインタが得られてコンパイルエラーになる。
未指定の場合、宣言順で関数ポインタが得られるようだ。

createLoader(&CSpriteBase::SetVisible,&CSpriteBase::IsVisible) );

メンバ関数ポインタは、ポインタの型に合わせて代入される関数が決定されるようなのだが、代入先がテンプレートになっているのでうまく行かない。
どうするかわからなかったが、以下のように書けばうまく行った。

createLoader((void(CSpriteBase::*)(bool))&CSpriteBase::SetVisible,&CSpriteBase::IsVisible) );

デバッガで追うと、きちんと意図した関数がコールされた。
これは、キャストすることでテンプレートの型が決定して、それで代入される型が確定して、関数ポインタが確定するのではないかと推測している。
この辺りのことが書かれているものを見たことはないので、正しいのかどうかはわからないが、動作は問題ない。

参考ページ:
オーバーロードした関数ポインタの取り方
関数のポインタとオーバーロード



投稿者 Takenori : 2008年01月01日 16:09




comments powered by Disqus
Total : Today : Yesterday : なかのひと