暗黙のインターフェースにconstを強要させる
テンプレートで静的ポリモーフィズムを実現するために暗黙のインタフェースを利用します。しかしこれは明示的なインターフェースと違い、引数がconst、あるいはインターフェースがconstメンバ関数かどうかまで通常指定することができません。しかしconstは便利で強力なので使いたい。それをしてみようというのがこの記事です。
言葉で説明しても分かりづらいですね。ということでconstを指定できないってことのサンプルコード
class Hoge{ public: void func(); void func2(Someting& Obj); }; class Bar{ public: void func()const; void func2(const Someting& Obj); }; template<typename T> class Foo{ public: func(){ Obj.func(); Obj.func2(Obj3); }; private: T Obj; Someting Obj3; };
としたとき
int main(){ Foo<Hoge> A; Foo<Bar> B; A.func(); B.func(); return 0; }
としてもエラーがでないんですね。
(1)暗黙のインターフェースをconstメンバ関数にする
こちらは割合簡単です。意識しないで利用していることも多いんじゃないでしょうか?
template<typename T> class Foo{ public: func() const{ Obj.func(); }; private: T Obj; Someting Obj3; };
みたいにすればテンプレートで指定したTのfuncをconstメンバ関数にしなければエラーをきちんとはきます。Fooのfuncがconstなのでそのメンバ関数であるObjも変更しちゃいけないということです。この例ではFooのfuncをpublicにしちゃっていますが、メンバ関数をconstにしたいだけで外部から呼び出してほしくないときはprivateなメンバ関数にすればいいかと思います。
(2)暗黙のインターフェースの引数をconstにする
こっちは分かってしまえば単純なのですが、なかなか気づかないです。
template<class T> class Foo{ public: void func(){ Obj.func2(const_cast<const Something&>(Parameter)); } private: T Obj; int a; Something Parameter; };
これで引数がconstになりました。通常はconst_castをconstではずす目的で利用することも多いですが、constをつけることもできるってのがミソです。多くのものでconstをはずすとしか紹介されてないので僕もEffective C++読むまでconstを付けられることを知りませんでした。
<追記>
VC++では予期したエラーはいてくれたのですがBCCではなぜかconstが効きませんでした...なんででしょうか?環境依存って怖いですよね。