暗黙のインターフェースに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が効きませんでした...なんででしょうか?環境依存って怖いですよね。