テンプレートメタプログラミングでいろいろ書いたメモ

// ビットからバイト、バイトからビットへ単位を変換
template<uint TValue>
struct bit_to_bytes
{
    static const uint value = TValue >> 3;
};
template<uint TValue>
struct byte_to_bits
{
    static const uint value = TValue << 3;
};

// 2 の TValue 乗
template<int TValue>
struct power2
{
    static const uint value = 1 << TValue;
};

namespace detail
{
    template<uint TValue, bool = TValue != 1>
    struct log2_helper
    {
        static const int value = 1 + log2<(TValue >> 1)>::value;
    };
    template<uint TValue>
    struct log2_helper<TValue, false>
    {
        static const int value = 0;
    };
}
// TValue が 2 の何乗か(小数点以下は切り捨て)
template<uint TValue>
struct log2
{
    static const int value = detail::log2_helper<TValue>::value;
};

// TValue が 2 の整数乗で表せるかどうか
template<uint TValue>
struct is_power2
{
    static const bool value = TValue == power2<log2<TValue>::value>::value;
};

namespace detail
{
    template<uint TValue, bool = is_power2<TValue>::value>
    struct floor2_helper
    {
        static const uint value = power2<log2<TValue>::value>::value;
    };
    template<uint TValue>
    struct floor2_helper<TValue, false>
    {
        static const uint value = power2<1 + log2<TValue>::value>::value;
    };
}
// TValue を 2 の整数乗に繰り上げた値を返す
template<uint TValue>
struct floor2
{
    static const uint value = detail::floor2_helper<TValue>::value;
    // static const uint value =
    //  power2<(1 - is_power2<TValue>::value) + log2<TValue>::value>::value;
};

// TValue を TAlign の単位にアライメントする
template<uint TValue, int TAlign>
struct alignment
{
    static const uint value = (TValue + TAlign - 1) / TAlign * TAlign;
};