関数テンプレートの引数のcv修飾を保持する

値渡しをすると引数のトップレベルのcv修飾は破棄されてしまいます。
そこでcv修飾を保持したければ、参照渡しで受けてやれば良いです。
参照渡しではconstを勝手に外すと関数内部でオリジナルの値が書き換えられてしまいかねないのでそのようなことは行われません。
以下はT1がconst修飾されていて、T2がconst修飾されていなかった場合に自動的にconst_castを呼ぶ例です。
条件分岐の際に、標準にis_pointer_to_constのようなメタ関数は無い気がするので自分で用意する必要がありそうです。

#include <type_traits>

template<class T>
struct is_pointer_to_const
{
    static constexpr bool value = false;
};

template<class T>
struct is_pointer_to_const<const T*>
{
    static constexpr bool value = true;
};

template<class T1, class T2>
static auto cast(T2& arg,
                 typename std::enable_if<!is_pointer_to_const<T1>::value>::type* = nullptr,
                 typename std::enable_if<is_pointer_to_const<T2>::value>::type* = nullptr
                 ) -> T1
{
    return const_cast<T1>(arg);
}

int main()
{
    const int* a = nullptr;
    cast<int*>(a);
}