Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ recursive template type deduction

I'm interested in learning a little about template meta-programming. In the code below I'm attempting to find an unsigned integral type large enough to hold N bits, specified at compile time, using some template recursion.

template <typename T>
struct NextIntegralType
{
};

template <>
struct NextIntegralType<void>
{
    typedef unsigned char type;
};

template <>
struct NextIntegralType<unsigned char>
{
    typedef unsigned short type;
};

...More type 'iteration' here...

template<size_t BITS, typename T>
struct FindIntegralType2
{
    typedef std::conditional<BITS <= sizeof(typename T::type)*8, T, FindIntegralType2<BITS, NextIntegralType<typename T::type>>> _type;
    typedef typename _type::type type;
};

template<size_t BITS>
struct FindIntegralType
{
    typedef typename FindIntegralType2<BITS, NextIntegralType<void>>::type type;
};

When I declare a variable and assign an integral value to it...

FindIntegralType<15>::type test(4000);

I get the following:

error: no matching function for call to ‘FindIntegralType2<15u, NextIntegralType<unsigned char> >::FindIntegralType2(int)’
note: candidates are:
note: constexpr FindIntegralType2<15u, NextIntegralType<unsigned char> >::FindIntegralType2()
note:   candidate expects 0 arguments, 1 provided
note: constexpr FindIntegralType2<15u, NextIntegralType<unsigned char> >::FindIntegralType2(const FindIntegralType2<15u, NextIntegralType<unsigned char> >&)
note:   no known conversion for argument 1 from ‘int’ to ‘const FindIntegralType2<15u, NextIntegralType<unsigned char> >&’

It seems like my recursion isn't 'unwinding'. Can anyone point me in the right direction?

Note: I'm using GCC 4.6.

EDIT:
I found a post that I missed before:
Automatically pick a variable type big enough to hold a specified number

Which points to an answer in boost (where they always are):
boost_integer

This should solve both my practical need and intellectual curiosity.

like image 576
TractorPulledPork Avatar asked May 23 '12 22:05

TractorPulledPork


1 Answers

Your problem is that _type::type evaluates to std::conditional<...>::type, not FindIntegralType2<...>::type. Change it to typedef typename _type::type::type type; (too much type x_X). This should solve your problem.

like image 81
Xeo Avatar answered Sep 21 '22 17:09

Xeo