P: n/a

I'm trying to get a feel for template metaprogramming, and so I'm trying
to write a compiletime "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,exp1>::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  
Share this Question
P: n/a

Frederick Gotham wrote:
I'm trying to get a feel for template metaprogramming, and so I'm trying
to write a compiletime "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,exp1>::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.  
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 compiletime "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,exp1>::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,exp1>::value
: base;
};
or something like that.
Tony  
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 compiletime "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,exp1>::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,exp1>::value
: base;
};
A conditional isn't a compile time expression, or am I missing something?

Ian Collins.  
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,exp1>::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
compiletime constants, if its operands are compiletime constants.
Which makes sense, because all the information is available at
compilation time, in every case.
Luke  
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,exp1>::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
compiletime constants, if its operands are compiletime 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.  
P: n/a

posted:
template<class T, T base, T exp>
struct IntPosPow {
static T const value = exp ? base * IntPosPow<T,base,exp1>::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  
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,exp1>::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, exp1,
!!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  
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,exp1>::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, exp1,
!!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, exp1>::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
 
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,exp1>::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  
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   This discussion thread is closed Replies have been disabled for this discussion.   Question stats  viewed: 1157
 replies: 10
 date asked: Jul 4 '06
