Search code examples
c++templatesconditional-statementstemplate-specialization

How can I specialize a C++ template for multiple ranges of integer values?


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).


Solution

  • 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;
    };