The following code does not work as expected (or at least as I expected). All versions of g++ that I tried fail at a template recursion limit. The output seems to indicate that the conditional statements are ignored and the final else block is used regardless of the value of P.
template <int P> inline REAL const_pow   ( REAL value );
template <     > inline REAL const_pow<0>( REAL value ) { return 1.0; }
template <     > inline REAL const_pow<1>( REAL value ) { return value; }
template <     > inline REAL const_pow<2>( REAL value ) { return value*value; }
template <int P> inline REAL const_pow   ( REAL value ) 
{
  if (P < 0)
    return const_pow<-P>( 1.0/value );
  else if (P % 2 == 0)
    return const_pow<2>( const_pow<P/2>(value) );
  else
    return value * const_pow<P-1>( value );
}
The problem doesn't seem to be with negative values (exclusively.) If I re-order the conditional such that the negative-value case is last, the last block is still taken every time.
I have a working solution using a helper class and more complex specialization. But this version was a lot more readable and should achieve the same effect (with optimization enabled). Why doesn't it work?
Keep in mind that all branches need to be compiled (evaluated at template-evaluation time) before the actual execution even begins! For that reason, const_pow<3> will try to instantiate const_pow<-3> even if it is ultimately never run. Which in return requires const_pow<3> again...
What you need is to disable template evaluation of incorrect branch alltogether. This can be resolved either through manually crafted type-traits, or through C++11 std::enable_if.
Try the following:
#include <iostream>
typedef float REAL;
template <int P> inline REAL const_pow   ( REAL value );
template <     > inline REAL const_pow<0>( REAL value ) { return 1.0; }
template <     > inline REAL const_pow<1>( REAL value ) { return value; }
template <     > inline REAL const_pow<2>( REAL value ) { return value*value; }
template <int P, bool negative>
struct const_pow_helper { //instantiate this when P is positive
        static inline REAL call(REAL value) {
                return const_pow<2>(const_pow<P / 2>(value)) * const_pow<P % 2>(value);
        }
};
template <int P>
struct const_pow_helper<P, true> { //instantiate this when P is negative
        static inline REAL call(REAL value) {
                return const_pow_helper<-P, false>::call(1.0/value);
        }
};
template <int P> inline REAL const_pow   ( REAL value )
{
        return const_pow_helper<P, P<0 >::call(value);
}
int main() {
        std::cout << const_pow<10>(2.0f) << std::endl;
        std::cout << const_pow<-10>(2.0f) << std::endl;
};
Notice that the negative version of the const_pow_helper will be instantiated only for negative P. This decision is handled by the template evaluator and not an ordinary if.
The if for the positive P has been avoided as well, by using integer division (P/2) and multiplying with the remainder value if it exists (P%2).
Solution with std::enable_if: (https://ideone.com/2lMjv1)
template <int P>
constexpr typename std::enable_if<P == 0, REAL>::type
const_pow(REAL ) { return 1.0; }
template <int P>
constexpr typename std::enable_if<P == 1, REAL>::type
const_pow(REAL value) { return value; }
template <int P>
constexpr typename std::enable_if<P == 2, REAL>::type
const_pow( REAL value ) { return value * value; }
template <int P>
constexpr typename std::enable_if<2 < P, REAL>::type
const_pow(REAL value)
{
    return const_pow<2>(const_pow<P / 2>(value)) * const_pow<P % 2>(value);
}
template <int P>
constexpr typename std::enable_if<P < 0, REAL>::type
const_pow(REAL value) { return const_pow<-P>(1.0 / value); }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With