By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,778 Members | 2,015 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,778 IT Pros & Developers. It's quick & easy.

Template metaprogramming

P: n/a

I'm trying to get a feel for template metaprogramming, and so I'm trying
to write a compile-time "Raise number to positive integer" algorithm. So
far, I have the following:

template<class T, T base, unsigned exp>
struct IntPosPow {

static T const value =
base * IntPosPow<T,base,exp-1>::value;
};

template<class T, T base>
struct IntPosPow<T,base,0{

static T const value = 1;

};
#include <iostream>

int main()
{
std::cout <<

(unsigned long)IntPosPow<unsigned long,2,0>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,1>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,2>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,3>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,4>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,5>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,6>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,7>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,8>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,9>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,10>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,11>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,12>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,13>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,14>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,15>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,16>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,17>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,18>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,19>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,20>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,21>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,22>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,23>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,24>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,25>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,26>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,27>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,28>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,29>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,30>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,31>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,32>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,33>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,34>::value << '\n' <<
(unsigned long)IntPosPow<unsigned long,2,35>::value << '\n';
}
Is there any way I can have:

template<class T, T base, T expstruct IntPosPow {
instead of:

template<class T, T base, unsigned expstruct IntPosPow {
?
--

Frederick Gotham
Jul 4 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Frederick Gotham wrote:
I'm trying to get a feel for template metaprogramming, and so I'm trying
to write a compile-time "Raise number to positive integer" algorithm. So
far, I have the following:

template<class T, T base, unsigned exp>
struct IntPosPow {

static T const value =
base * IntPosPow<T,base,exp-1>::value;
};

template<class T, T base>
struct IntPosPow<T,base,0{

static T const value = 1;

};
#include <iostream>

int main()
{
std::cout <<

(unsigned long)IntPosPow<unsigned long,2,0>::value << '\n' <<
Why the cast? IntPosPow<unsigned long,2,0>::value is unsigned long.
Is there any way I can have:

template<class T, T base, T expstruct IntPosPow {
instead of:

template<class T, T base, unsigned expstruct IntPosPow {

I don't think so. The specialised template won't match.

Considering your task is to "Raise number to positive integer", why
would you want to use anything else?

--
Ian Collins.
Jul 4 '06 #2

P: n/a

Ian Collins wrote:
Frederick Gotham wrote:
I'm trying to get a feel for template metaprogramming, and so I'm trying
to write a compile-time "Raise number to positive integer" algorithm. So
far, I have the following:

template<class T, T base, unsigned exp>
struct IntPosPow {

static T const value =
base * IntPosPow<T,base,exp-1>::value;
};

template<class T, T base>
struct IntPosPow<T,base,0{

static T const value = 1;

};

Is there any way I can have:

template<class T, T base, T expstruct IntPosPow {
instead of:

template<class T, T base, unsigned expstruct IntPosPow {
I don't think so. The specialised template won't match.
Don't specialize, use ?:

template<class T, T base, T exp>
struct IntPosPow {

static T const value = exp ? base * IntPosPow<T,base,exp-1>::value
: base;
};
or something like that.

Tony

Jul 4 '06 #3

P: n/a
go**********@gmail.com wrote:
Ian Collins wrote:
>>Frederick Gotham wrote:
>>>I'm trying to get a feel for template metaprogramming, and so I'm trying
to write a compile-time "Raise number to positive integer" algorithm. So
far, I have the following:

template<class T, T base, unsigned exp>
struct IntPosPow {

static T const value =
base * IntPosPow<T,base,exp-1>::value;
};

template<class T, T base>
struct IntPosPow<T,base,0{

static T const value = 1;

};

Is there any way I can have:

template<class T, T base, T expstruct IntPosPow {
instead of:

template<class T, T base, unsigned expstruct IntPosPow {


I don't think so. The specialised template won't match.


Don't specialize, use ?:

template<class T, T base, T exp>
struct IntPosPow {

static T const value = exp ? base * IntPosPow<T,base,exp-1>::value
: base;
};
A conditional isn't a compile time expression, or am I missing something?

--
Ian Collins.
Jul 4 '06 #4

P: n/a
Ian Collins wrote:
go**********@gmail.com wrote:
Don't specialize, use ?:

template<class T, T base, T exp>
struct IntPosPow {

static T const value = exp ? base * IntPosPow<T,base,exp-1>::value
: base;
};
A conditional isn't a compile time expression, or am I missing something?
You are missing something. The ternary operator can be used to produce
compile-time constants, if its operands are compile-time constants.
Which makes sense, because all the information is available at
compilation time, in every case.

Luke

Jul 4 '06 #5

P: n/a
Luke Meyers wrote:
Ian Collins wrote:
>>go**********@gmail.com wrote:
>>>Don't specialize, use ?:

template<class T, T base, T exp>
struct IntPosPow {

static T const value = exp ? base * IntPosPow<T,base,exp-1>::value
: base;
};

A conditional isn't a compile time expression, or am I missing something?


You are missing something. The ternary operator can be used to produce
compile-time constants, if its operands are compile-time constants.
Which makes sense, because all the information is available at
compilation time, in every case.
Good point, I hadn't thought of using the operator in metaprogramming,
I'd always used specialisation.

--
Ian Collins.
Jul 4 '06 #6

P: n/a
posted:
template<class T, T base, T exp>
struct IntPosPow {

static T const value = exp ? base * IntPosPow<T,base,exp-1>::value
: base;
};

Won't work.

When the compiler makes a specialisation where "exp" is 0, it has to make
an another specialisation where "exp" is 0, and another "exp" where
"exp" is 0. It's exactly like:
struct Arb {

enum { base = 3 };
enum { exp = 7 };

static unsigned const value = exp ? base * Arb::value : base;
};
int main()
{
Arb::value;
}
The programmer's explicit specialisation is necessary.
--

Frederick Gotham
Jul 4 '06 #7

P: n/a

Frederick Gotham wrote:
posted:
template<class T, T base, T exp>
struct IntPosPow {

static T const value = exp ? base * IntPosPow<T,base,exp-1>::value
: base;
};


Won't work.

When the compiler makes a specialisation where "exp" is 0, it has to make
an another specialisation where "exp" is 0, and another "exp" where
"exp" is 0. It's exactly like:
yeah, when I actually tried it, it crashed the compiler (MSVC 8.0).
>
The programmer's explicit specialisation is necessary.
Right, but we can still do that without forcing a type, by converting
the T exp into an extra bool param, then specializing on that:
template <typename T, T base, T exp, bool b = !!exp>
struct IntPosPow
{
static T const value = base * IntPosPow<T , base, exp-1,
!!exp>::value;
};

template <typename T, T base, T exp>
struct IntPosPow<T, base, exp, false>
{
static T const value = 1;
};

I think that one even compiles.

- Tony

Jul 4 '06 #8

P: n/a

go**********@gmail.com wrote:
Frederick Gotham wrote:
posted:
template<class T, T base, T exp>
struct IntPosPow {
>
static T const value = exp ? base * IntPosPow<T,base,exp-1>::value
>: base;
};

Won't work.

When the compiler makes a specialisation where "exp" is 0, it has to make
an another specialisation where "exp" is 0, and another "exp" where
"exp" is 0. It's exactly like:

yeah, when I actually tried it, it crashed the compiler (MSVC 8.0).

The programmer's explicit specialisation is necessary.

Right, but we can still do that without forcing a type, by converting
the T exp into an extra bool param, then specializing on that:
template <typename T, T base, T exp, bool b = !!exp>
struct IntPosPow
{
static T const value = base * IntPosPow<T , base, exp-1,
!!exp>::value;
};
screwed up again (thought I should actually run it and see what I got).
I had that extra !!exp in there when I was trying things out. It
should be just like your original:

template <typename T, T base, T exp, bool b = !!exp>
struct IntPosPow
{
static T const value = base * IntPosPow<T , base, exp-1>::value;
};

Tony
template <typename T, T base, T exp>
struct IntPosPow<T, base, exp, false>
{
static T const value = 1;
};

I think that one even compiles.

- Tony
Jul 4 '06 #9

P: n/a
Tony posted:
>Right, but we can still do that without forcing a type, by converting
the T exp into an extra bool param, then specializing on that:

Here's the complete working example. (Note that the double inversion
operators were redundant).
template <typename T, T base, T exp, bool b = exp>
struct IntPosPow
{
static T const value = base * IntPosPow<T,base,exp-1>::value;
};

template <typename T, T base, T exp>
struct IntPosPow<T,base,exp,false>
{
static T const value = 1;
};

#include <iostream>

int main()
{
std::cout << IntPosPow<unsigned,2,13>::value;
}
--

Frederick Gotham
Jul 4 '06 #10

P: n/a

Frederick Gotham wrote:
Tony posted:
Right, but we can still do that without forcing a type, by converting
the T exp into an extra bool param, then specializing on that:


Here's the complete working example. (Note that the double inversion
operators were redundant).
Most compilers will give you a warning when you convert int (or
whatever T is) to bool ("potential loss of data" or similar). Even an
explicit (bool) cast doesn't usually quiet the compiler. But !! does.
I suppose it depends on the compiler and warning levels, but I've seen
it enough to just make it a habit. It also makes the intent more
explicit, like saying 'I meant to do that' - ie I really did want to
convert this int to a bool. For people that haven't seen !! I guess it
isn't very communicative, but the idiom is fairly well know, and by
emplying it I hope to make it more well known...

Tony

Jul 4 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.