I'm trying to create a template class for handling bit streams. I'd like to have an underlying integer type declared in the template that would resolve to either uint8_t
, uint16_t
, uint32_t
or uint64_t
, depending on the template argument (an int, number of bits). I found the two answers regarding this subject (How can I specialize a C++ template for a range of integer values? and Integer range based template specialisation) and implemented the following code:
template<int BITS>
class MyClass {
typedef typename
std::conditional< BITS <= 8, uint8_t,
std::conditional< BITS <= 16, uint16_t,
std::conditional< BITS <= 32, uint32_t, uint64_t > > >::type
int_type;
...
}
In my program, I instantiate MyClass<32>
, but when compiling this, I'm getting the following error:
no known conversion for argument 1 from ‘uint32_t {aka unsigned int}’ to ‘MyClass<32>::int_type {aka std::conditional<false, short unsigned int, std::conditional<true, unsigned int, long unsigned int> >}’
If I'm instantiating MyClass<8>
instead, everything works. So it looks like only the first level of std::conditional
is actually expanded.
Any idea how to do this correctly?
Edit: I haven't stated this before, but I'm looking for a solution which would also work for any bit size instantiation (as long as it's 64 bits at most). So I'd like MyClass<27>
to work as well (selecting uint32_t
).
To answer your edit and make your original code work.
template<int BITS>
class MyClass {
using int_type =
typename std::conditional< BITS <= 8, uint8_t,
typename std::conditional< BITS <= 16, uint16_t,
typename std::conditional< BITS <= 32, uint32_t, uint64_t >::type >::type >::type;
public:
int_type i;
};