Flat Leon Works

アプリやゲームを作ってます。

【C++ アイデア】const_castをちょっと楽にする

const_castはちょっと手間

const_castconstを付けたり外したりするためのキャストなのですが、ちょっと記述が面倒です。

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が少し面倒なのは、多用させないという意図もあるのかもしれません。注意して使いましょう。