constexpr pow via template metaprogramming

http://ideone.com/ZYgFmr
1
2
3
4
5
6
7
8
template<typename T, T b, T e>
struct constexpr_pow : std::integral_constant<T, b*constexpr_pow<T, b, e-1>::value>
{
};
template<typename T, T b>
struct constexpr_pow<T, b, 1/*<-error*/> : std::integral_constant<T, b>
{
};
How can I accomplish this? I don't know how to handle the error.

Note: I am aware it is no good for negative exponents, that's fine.
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

template < typename T, T b, unsigned int e >
struct pow : std::integral_constant< decltype(b*1), b * pow<T,b,e-1>::value > {} ;

template < typename T, T b >
struct pow<T,b,0> : std::integral_constant< decltype(b*1), T(1) > {} ;

int main()
{
    std::cout << pow< char, 'd', 3 >::value << '\n' ;
}

http://ideone.com/oU9MRg
Last edited on
Ah, I feel kind of silly for that now. Thankyou!

Though, shouldn't line 7 use (decltype(b*1))(1) instead of T(1)?
Last edited on
> Though, shouldn't line 7 use (decltype(b*1))(1) instead of T(1)

decltype(b*1) is the type after integral promotion (if any) has been applied; T(1) would be promoted if required.

ie. in std::integral_constant< int, char('a') >, the char is promoted.
closed account (o1vk4iN6)
You can just use some easier cleaner syntax with the introduction of constexpr:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

constexpr int pow(int v, int e)
{
	return (e == 0) ? 1 : v * pow(v, e - 1);
}

int main()
{
	
	static const int size = pow(2,3);
	int arr[ size ];
	
	std::cout << size;
	
	return 0;
}


http://ideone.com/pS1B4i
Yes, I was trying to do it with templates ;)
Templates can be used in conjunction with constexpr.
A function would be more flexible - the type is not limited to integral types.

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

template < typename T >
constexpr auto pow( T b, unsigned int e ) -> decltype(b+1)
{ return e ? b * pow( b, e-1 ) : 1 ; }

int main()
{
    constexpr double test = pow( 1.99f, 7 ) ;
    char cstr[ int( test + 0.5 ) ] = "" ;
    std::cout << test << ' ' << sizeof(cstr) << '\n' ; // 123.587 124
}

Note: The compile-time evaluation of pow( 1.99f, 7 ) normally would, but need not yield precisely the same value as its run-time evaluation.
note that your template approach has O(n) recursion depth, so you can't go too far. As with much of template metaprogramming, it benefits from divide-and-conquer style O(log n) recursion depth solutions, for example see static_pow in this post http://stackoverflow.com/a/19831565/273767 (which also demonstrates a TMP n'th root!)
Last edited on
> As with much of template metaprogramming, it benefits from divide-and-conquer style
> O(log n) recursion depth solutions

Yes, thanks Cubbi.

In this paricular case (class template), it doesn't buy much though; n can't get uncomfortably big for n'th power / n'th root of integer types.
Last edited on
Topic archived. No new replies allowed.