
Hervé Brönnimann <hervebronnimann <at> mac.com> writes:
That would also have been my implementation:
template <int N> struct positive_power { template <typename T> static typename tools::promote_args<T>::type result(T base) { typename tools::promote_args<T>::type power = positive_power<N/2>::result(base); return (N%2) ? base * power *power : power * power; } };
with the two specializations:
template <> struct positive_power<0> { template <typename T> static typename tools::promote_args<T>::type result(T base) { return 1; } };
template <> struct positive_power<1> { template <typename T> static typename tools::promote_args<T>::type result(T base) { return base; } };
(strictly speaking, <0> only is needed, but the compiler may not know to optimize multiplying by T(1), which is one criticism of previous post by John Moeller, who proposes essentially the same solution but with a factor ((N%2) ? base : 1) that I don't like).
Fair enough. I think, though, if you're going to try to make sure that the compiler doesn't miss multiplication by 1, you may as well go all the way and add another template parameter to capture N%2, and get rid of the ternary statement: template <int N, int M = N%2> struct positive_power; template <int N> struct positive_power<N, 0> { template <typename T> static typename tools::promote_args<T>::type result(T base) { typename tools::promote_args<T>::type power = positive_power<N/2,(N/2)%2>::result(base); return power * power; } }; template <int N> struct positive_power<N, 1> { template <typename T> static typename tools::promote_args<T>::type result(T base) { typename tools::promote_args<T>::type power = positive_power<N/2,(N/2)%2>::result(base); return base * power * power; } }; with the two specializations: template <> struct positive_power<0,0> { template <typename T> static typename tools::promote_args<T>::type result(T base) { return 1; } }; template <> struct positive_power<1,1> { template <typename T> static typename tools::promote_args<T>::type result(T base) { return base; } }; Now all the compiler has to do is spit out multiplications, assuming that things are inlined well.