I would like to create a class template which takes an unsigned integer parameter and has a member u_ whose type is the smallest unsigned integer type that will
This piece of metaprogramming trickery achieves it:
template struct typed
{
typedef typename typed<(Y & (Y - 1)) == 0 ? Y / 2 : (Y & (Y - 1))>::type type;
};
template<> struct typed<0>
{
typedef std::uint8_t type;
};
template<> struct typed<256>
{
typedef std::uint16_t type;
};
template<> struct typed<65536>
{
typedef std::uint32_t type;
};
/* ToDo - add more specialisations as necessary*/
template class A
{
public:
unsigned static const k_ = k; /*constexpr if your compiler supports it*/
typename typed::type u_;
};
The usage is exactly in the question.
The unspecialised template version takes the previous type. typed<0> blocks the static recursion. The other specialisations act as anchoring points for the appropriate types.
The compile-time evaluable (Y & (Y - 1)) == 0 ? Y / 2 : (Y & (Y - 1)) reduces the number of instantiations by removing the rightmost bit of Y until a power of 2 is reached, and then divides by 2 subsequently to that. (Acknowledge @Jarod42).