вычисления на стадии компилляции
От: Флоров В.М. Россия  
Дата: 29.05.02 05:30
Оценка:
навеяно сообщениями 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 такой изврат делается, что приятно.
вот только сложновато вроде, как можно поупростить?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.