Вычисление и печать факториала во время компиляции на языке C++


template<unsigned int n>
struct Factorial {
    enum { value = n * Factorial<n-1>::value};
};

template<>
struct Factorial<0> {
    enum {value = 1};
};

int main() {
    std::cout << Factorial<5>::value;
    std::cout << Factorial<10>::value;
}

Вышеуказанная программа вычисляет факторное значение во время компиляции. Я хочу печатать факториальное значение во время компиляции, а не во время выполнения с помощью cout. Как мы можем добиться печати факториального значения во время компиляции?

Я использую VS2009.

Спасибо!

3 22

3 ответа:

Факториал может быть напечатан в сгенерированном компилятором сообщении следующим образом:

template<int x> struct _;
int main() {
        _<Factorial<10>::value> __;
        return 0;
}

Сообщение об ошибке:

Прог.cpp: 14: 32: error: aggregate '_ _ _ ' имеет неполный тип и не может быть определен _::значение> __; ^

Здесь 3628800 является факториалом 10.

Смотрите его в ideone: http://ideone.com/094SJz

Так вы ищете это?


Правка:

Матье попросил умного фокус в том, чтобы одновременно напечатать факториал и позволить компиляции продолжаться. Вот одна попытка. Он не выдает никаких ошибок, поэтому компиляция завершается с одним предупреждением.

template<int factorial> 
struct _{ operator char() { return factorial + 256; } }; //always overflow
int main() {
        char(_<Factorial<5>::value>());
        return 0;
}

Он компилируется с этим предупреждением:

Главная.cpp: в экземпляре'_:: operator char () [с int факториал = 120]': главное.cpp: 16: 39: требуется отсюда главный.cpp: 13: 48: предупреждение: переполнение при неявном преобразовании констант [- Woverflow] struct _{ оператор char () { возвращаемый факториал + 256; } }; //всегда переполнение

Здесь 120 является факториалом 5.

Демо в ideone: http://coliru.stacked-crooked.com/a/c4d703a670060545

Вы можете просто написать хороший макрос и использовать его вместо этого как:

#define PRINT_AS_WARNING(constant) char(_<constant>())    

int main() 
{
         PRINT_AS_WARNING(Factorial<5>::value);
         return 0;
}

Это выглядит великолепно.

Я изучаю основы TMP и хочу знать результат при компиляции, чтобы убедиться, что логика верна.

В этом случае то, что вы действительно хотите, - это статическое утверждение:

static_assert(Factorial<5> ::value ==     120,  "5! should be 120");
static_assert(Factorial<10>::value == 3628800, "10! should be 3628800");

Если ваш компилятор еще не поддерживает static_assert, Вы можете использовать BOOST_STATIC_ASSERT.

Определенно нет стандартного способа. Я также не могу придумать способ, специфичный для компилятора.

[[наполнитель]]