2016-06-16 6 views
0

ビットの上半分だけを取得するためにビットマスクを適用したい。だから、UINT32のためには、これを次のようになります。データタイプに応じたビットマスク

uint32_t version_part = oldID & 0xFFFF0000; 

これは、データ型がハードコードされたときに、すべての罰金ですが、これはテンプレート機能だったと私はarbritaryデータ型を提供したい場合(uint8_t、uint16_t、... )ビットマスクのサイズを比例して(0xF0、0xFF00、...)、コンパイル時に調整することが大切です。

有限個のデータ型があるとしたら、if-case(静的な場合は?)を作ることができますが、それを行うにはより良い方法があるのだろうかと思っていました。

答えて

2

あなたの目的は以下のようなものですか?

template<typename T> 
T maskbits(T oldID) 
{ 
    const size_t SZ = sizeof oldID * CHAR_BIT; 
    const T mask = (static_cast<T>((1ULL << (SZ/2)) - 1ULL)) << (SZ/2); 
    return oldID & mask; 
} 
+1

が有望に見えるコンパイル時にマスクを生成することができ、コンパイラを有効にチェックし、最適化! – KaiserJohaan

+0

もっと見ると分裂はあまりありませんか?関数の2行目で、なぜSZをもう一度半分にする必要がありますか? – KaiserJohaan

+0

@KaiserJohaanはい、そうです、修正しましょう。 –

2

Mohit Jainの回答が良いです。テンプレートを使用しているので、しかし、あなたはまた、テンプレートの特殊化で何かができる:ここ

/* general case */ 
template<typename T> class Mask { }; 

/* specific cases */ 
template<> class Mask<uint16_t> {public: static const uint16_t value = 0xFF00; }; 
template<> class Mask<uint32_t> {public: static const uint32_t value = 0xFFFF0000; }; 
/* etc. */ 

template<typename T> 
T maskbits(T uid) 
{ 
    return uid & Mask<T>::value; 
} 

大きなプラスは、あなたがサポートされていないタイプにコンパイルエラーを取得するには、空白一般的なケースを残すことができます。もちろん、必要に応じてマスクを計算することもできます。

+1

あなたはそれに言及したので、それはすべて一定です。コンパイラはおそらくそれらの計算をコンパイル時に行うでしょう。 – Joris

1

おそらくあなたはこれを試すことができます、それは任意の整数サイズで動作します。

#include <iostream> 

template<typename T> 
T mask(T a = 0) { 
    return (~T(0)) << 4*sizeof(T); 
} 

int main() 
{ 
    unsigned char v = mask<unsigned char>(); 
    int v2 = mask(32); 
    std::cout << "v = 0x" << std::hex << (unsigned int)v << std::endl; 
    std::cout << "v2 = 0x" << std::hex << (unsigned int)v2 << std::endl; 
} 

出力は次のようになります。

v = 0xf0 
v2 = 0xffff0000 

編集:私はちょうど、おかげでそれをしようと、

+0

最適化に関係なくコンパイル時にマスクを作成したい場合は、 'constexpr'を使うことができると思います。 –

関連する問題