Подтвердить что ты не робот

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

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.

Спасибо!

4b9b3361

Ответ 1

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

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

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

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

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

Посмотрите на идеон: http://ideone.com/094SJz

Итак, вы ищете это?


EDIT:

Matthieu попросил умный трюк, чтобы напечатать факториал И пусть компиляция продолжается. Вот одна попытка. Это не дает никакой ошибки, поэтому компиляция успешно с одним предупреждением.

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

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

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

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

Демо на идеоне: http://coliru.stacked-crooked.com/a/c4d703a670060545

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

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

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

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

Ответ 2

Я изучаю основы 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.

Ответ 3

Определенно нет стандартного способа. Я тоже не думаю о компиляторе.

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