2016-06-16 4 views
0

Я хочу применить битовую маску, чтобы получить только верхнюю половину бит. Поэтому для uint32 было бы это:Бит-маска в зависимости от типа данных

uint32_t version_part = oldID & 0xFFFF0000; 

Это все хорошо, когда тип данных жёстко, но если это была шаблонная функция, и я хотел, чтобы обеспечить arbritary типа данных (uint8_t, uint16_t, ...) Я хочу изменить размер битмаски пропорционально (0xF0, 0xFF00, ...) и намного лучше во время компиляции.

Учитывая, что существует конечное число типов данных, я полагаю, вы могли бы просто сделать if-cases (static if?), Но мне было интересно, есть ли более хороший способ сделать это.

ответ

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

С другой стороны, слишком много деления? Во второй строке функции, почему 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

Теперь, когда вы упоминаете об этом, все это постоянно. Компилятор, вероятно, выполнит эти вычисления в compule-time. – 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 

Edit: Я только что проверил и с оптимизацией включен компилятор может производить маски во время компиляции

+0

Если вы хотите принудительно сделать маски во время компиляции независимо от оптимизации, я думаю, вы можете использовать 'constexpr'. –

Смежные вопросы