Расчет и печать факториала во время компиляции в C ++ - PullRequest
23 голосов
/ 12 февраля 2011
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.

Спасибо!

Ответы [ 4 ]

33 голосов
/ 12 февраля 2011

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

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

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

prog.cpp: 14: 32: ошибка: агрегат ‘_ <3628800> __’ имеет неполный тип и не может быть определен _ :: value> __; ^

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

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

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


EDIT:

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

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.

Демонстрация на 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;
}

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

7 голосов
/ 12 февраля 2011

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

1 голос
/ 25 февраля 2019

Я уверен, что уже слишком поздно, но все же.

// definition
template<typename T, T N>
struct print_constexpr{
    [[deprecated]]
    print_constexpr(){ }
};

// usage
print_constexpr<unsigned int, Factorial<5>::value> x;

// output
{path to file}: warning: ‘print_constexpr<T, N>::print_constexpr() [with T = unsigned int; T N = 120]’ is deprecated [-Wdeprecated-declarations]
    print_constexpr<unsigned int, Factorial<5>::value> x;
0 голосов
/ 12 февраля 2011

Стандартного пути точно не существует. Я тоже не могу придумать пути, специфичного для компилятора.

[[Filler]]

...