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 10 1309
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.
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 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.
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
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.
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
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 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
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
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. Similar topics
reply
views
Thread by Dave 
last post: by

12 posts
views
Thread by Dave 
last post: by

5 posts
views
Thread by Mohammad 
last post: by

21 posts
views
Thread by Protoman 
last post: by

5 posts
views
Thread by Mark Stijnman 
last post: by

7 posts
views
Thread by Joe 
last post: by

1 post
views
Thread by Ted 
last post: by
 
3 posts
views
Thread by stdlib99 
last post: by

12 posts
views
Thread by nooneinparticular314159 
last post: by
          