const_castはちょっと手間
const_cast
はconst
を付けたり外したりするためのキャストなのですが、ちょっと記述が面倒です。
class PlayerCharacter{}; const PlayerCharacter player; PlayerCharacter* p = const_cast<PlayerCharacter*>( &player ); // const外し const PlayerCharacter* const_pointer = const_cast<const PlayerCharacter*>( pointer ); // const付け
ここに注目
const_cast<PlayerCharacter*>( &player )
player
の型は分かっているのになぜPlayerCharacter
を記述しなければいけないのか。
const_off( &player )
こういうふうに書けてもいいんじゃないかと思いませんか?
const_on / const_off 関数を作る
作ってみました。
template< class T > const T* const_on( T* ptr ) { return const_cast<const T*>( ptr ); } template< class T > const T& const_on( T& ref ) { return const_cast<const T&>( ref ); } template< class T > T* const_off( const T* ptr ) { return const_cast<T*>( ptr ); } template< class T > T& const_off( const T& ref ) { return const_cast<T&>( ref ); }
使い方
class A{}; A& ref_A = const_off( a ); // const外し(参照) A* pointer_A = const_off( &a ); // const外し(ポインタ) const A& const_ref_A = const_on( ref_A ); // const付け(参照) const A* const_pointer_A = const_on( pointer_A ); // const付け(ポインタ) // ※constを付けるのはキャスト不要だったりする const A& const_ref_A2 = ref_A; const A* const_pointer_A2 = pointer_A;
const
を付加するのはキャスト不要なのですが、const
でオーバーロードされたメンバ関数を呼び出すために使ったりします。
class A { std::map<string,int> m_NamedValue; public: const int* GetValue( const char* p_name ) const { std::map<string,int>::const_iterator it = m_NamedValue.find( p_name ); if ( it != m_NamedValue.end() ) { return &(*it).second; } return NULL; } int* GetValue( const char* p_name ) { // 処理は同じなのでconst版の処理を呼び出す // const_on( this )でconst版GetValueを呼ぶ。そしてconst_offで戻り値のconstを外す。 return const_off( const_on( this )->GetValue( p_name ) ); /* const_on / const_off を使わない場合 return const_cast<int*>( const_cast<const A*>( this )->GetValue( p_name ) ); */ } };
まとめ
const_cast
を楽にするconst_on / const_off関数を紹介しました。しかし、const
外しは多用すべきではありません。const_cast
が少し面倒なのは、多用させないという意図もあるのかもしれません。注意して使いましょう。