暗黙の型変換を禁止するテンプレートクラス
暗黙の型変換はときおり悩まされる。しかも、コンパイラは警告すら出さない。
先日複数の引数がある関数をつくり、それでint型とbool型を受け取っていた。この場合型が異なるし独自の型を導入しなくてもいいだろうとか思っていたのが間違いだった。int型の変数にboolの値を代入するときエラーは愚か警告すら出ずしばらく悩んでいた。
ようするに以下のコードがコンパイルを通ってしまうのだ。
int main(){ int hoge =true; }
これは非常に気持ち悪い。ということでこれを禁止するために以下のようなテンプレートクラスを書いた。
template<typename T>
class StrictType{
public:
template<typename U>
StrictType(U){
static_assert(false, "bad cast");
}
template<>
StrictType<T>(T obj):
data(obj)
{}
operator T() const{return data;}
private:
const T data;
};変換コンストラクタをテンプレートメンバ関数にしてオーバーライドにより条件分岐している。テンプレートのほうが呼ばれた場合、テンプレートversionのメンバ関数が生成されるのでそこでstatic_assertでエラーを吐くというわけだ。
実際に使う時は合理的に見える継承関係にあるクラスとかポインタの処理を加えたほうがいいかもしれない。あと変換関数をもっと何とかしたい...