c++ - Unexpected template behavior with int parameter: conditional expressions ignored? -


the following code not work expected (or @ least expected). versions of g++ tried fail @ template recursion limit. output seems indicate conditional statements ignored , final else block used regardless of 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 negative values (exclusively.) if re-order conditional such negative-value case last, last block still taken every time.

i have working solution using helper class , more complex specialization. version lot more readable , should achieve same effect (with optimization enabled). why doesn't work?

keep in mind all branches need compiled (evaluated @ template-evaluation time) before actual execution begins! reason, const_pow<3> try instantiate const_pow<-3> if never run. in return requires const_pow<3> again...

what need disable template evaluation of incorrect branch alltogether. can resolved either through manually crafted type-traits, or through c++11 std::enable_if.

try 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 when p 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 when p 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 negative version of const_pow_helper instantiated negative p. decision handled template evaluator , not ordinary if.

the if positive p has been avoided well, using integer division (p/2) , multiplying remainder value if exists (p%2).


Comments

Popular posts from this blog

c++ - OpenCV Error: Assertion failed <scn == 3 ::scn == 4> in unknown function, -

php - render data via PDO::FETCH_FUNC vs loop -

The canvas has been tainted by cross-origin data in chrome only -