навеяно сообщениями Mishka<T> "Ответ Майерсу 2" и вопросом на Исходниках.ру по поводу возведения в степень.
как народ оценивает мысль переложения вычисления сложных констант на период компилляции? Вот что у меня получилось.
#include <iostream>
typedef unsigned char powered;
//==============================================================================
// вычисление x в степенях 2.
//==============================================================================
template < double x, powered y, powered flag >
struct x_pow_2nd
{
static double res;
};
//------------------------------------------------------------------------------
template < double x, powered y, powered flag >
double x_pow_2nd< x, y, flag >::res =
x_pow_2nd< x, y/2, flag >::res
* x_pow_2nd< x, y/2, flag >::res;
//==============================================================================
// специализация для случая flag = 0 - res == всегда 1
//==============================================================================
template < double x, powered y>
struct x_pow_2nd<x, y, 0>
{
static double res;
};
//------------------------------------------------------------------------------
template < double x, powered y >
double x_pow_2nd< x, y, 0 >::res = 1;
//==============================================================================
// специализация для степени 1 (прекращение рекурсии)
//==============================================================================
template < double x, powered flag >
struct x_pow_2nd <x, 1, flag >
{
static double res;
};
//------------------------------------------------------------------------------
template < double x, powered flag >
double x_pow_2nd< x, 1, flag >::res = x;
//==============================================================================
// специализация для степени 1 (прекращение рекурсии)
//==============================================================================
template < double x >
struct x_pow_2nd <x, 1, 0 >
{
static double res;
};
//------------------------------------------------------------------------------
template < double x >
double x_pow_2nd< x, 1, 0 >::res = 1;
//==============================================================================
// специализация для степени 0 (прекращение рекурсии)
//==============================================================================
template < double x, powered flag >
struct x_pow_2nd <x, 0, flag >
{
static double res;
};
//------------------------------------------------------------------------------
template < double x, powered flag >
double x_pow_2nd< x, 0, flag >::res = 1;
//==============================================================================
// основной шаблон.
//==============================================================================
template < double x, powered y, powered level = (1 << (sizeof(powered)*8 - 1)) >
struct x_pow_y
{
static double res;
enum { y_and_level = y & level };
};
//------------------------------------------------------------------------------
template < double x, powered y, powered level >
double x_pow_y< x, y, level >::res =
x_pow_2nd< x, level, y_and_level >::res
* x_pow_y< x, y, level/2 >::res;
//==============================================================================
// специализация основного шаблона, которая прекращает рекурсию для случая
// level == 0
//==============================================================================
template < double x, powered y >
struct x_pow_y< x, y, 0 >
{
static double res;
};
//------------------------------------------------------------------------------
template < double x, powered y >
double x_pow_y< x, y, 0 >::res = 1;
//==============================================================================
int main(int argc, char* argv[])
{
std::cout << x_pow_y<4.23, 13>::res;
return 0;
}
жаль вот только, что по стандарту нельзя использовать в параметрах шаблонов константы с плавающей точкой, но хоть на gcc такой изврат делается, что приятно.
вот только сложновато вроде, как можно поупростить?