【问题标题】:Calculating and printing factorial at compile time in C++在 C++ 编译时计算和打印阶乘
【发布时间】:2011-06-26 01:12:34
【问题描述】:
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。

谢谢!

【问题讨论】:

  • 为什么简单的事情要做复杂的事情?如果您只需要计算阶乘,编写一个常用程序(不带 TMP),编译并运行它。
  • 我正在学习 TMP 的基础知识,想知道编译时的结果以确保逻辑正确
  • @user:TMP 基本上是一种在编译时计算常量的方法。您希望以哪种形式完成输出?在预处理器中为时过早(常量稍后计算),在“通常”编译步骤中,您只能使用cout 等输出(需要运行程序)。

标签: c++ templates compile-time


【解决方案1】:

阶乘可以在编译器生成的消息中打印为:

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

错误信息:

prog.cpp:14:32: 错误:聚合 ‘_ __’ 类型不完整,无法定义 _::值> __; ^

这里362880010 的阶乘。

在 ideone 上查看:http://ideone.com/094SJz

那么你在找这个吗?


编辑:

Matthieu 要求一个聪明的技巧来打印阶乘并让编译继续。这是一种尝试。它没有给出任何错误,因此编译成功并出现一个警告。

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

编译时出现以下警告:

main.cpp:在 '_::operator char() 的实例化中 [with int factorial = 120]': main.cpp:16:39: 从这里需要 main.cpp:13:48:警告:隐式常量转换溢出 [-Woverflow] struct _{ operator char() { return factorial + 256; } }; //总是溢出

这里1205 的阶乘。

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;
}

那个looks great

【讨论】:

  • 很好的答案,但您不应该使用保留符号(___)。
  • 代码的目的是导致错误。不要认为保留名称适用于此。
  • 哇哦,这确实一种在编译期间打印东西的方法。 :) 很好地滥用编译器,+1。
  • @Nawaz: nice :) 你知道在编译期间打印结果并让编译继续进行吗?
  • @Nawaz:这很聪明 :) 更重要的是,_ 确实可以用于打印任何结果......只要确保它溢出是肯定的 :)
【解决方案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】:

我确信为时已晚,但仍然如此。

// 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;

【讨论】:

    【解决方案4】:

    绝对没有标准的方法。我也想不出编译器特有的方法。

    [[填充物]]

    【讨论】:

    • 我什至不确定是否有办法。我能想到的所有#pragma message#warning 通常都会打印该行,而不是计算结果:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 2010-11-25
    • 1970-01-01
    相关资源
    最近更新 更多