【问题标题】:Practical limitations on amount of constexpr computationconstexpr 计算量的实际限制
【发布时间】:2016-06-27 17:38:31
【问题描述】:

作为一个实验,我只是把一些代码放在一起,在编译时生成一个std::array<uint32_t, 256>。表内容本身是一个相当典型的 CRC 查找表 - 唯一的新功能是使用 constexpr 函数来计算条目,而不是直接在源代码中放置一个自动生成的魔法表。

无论如何,这个练习让我很好奇:编译器愿意在编译时评估 constexpr 函数或变量定义的计算量是否有任何实际限制?例如类似于 gcc 的 -ftemplate-depth 参数对模板元编程评估的数量产生了实际限制。 (我还想知道参数包的长度是否存在实际限制——这会限制使用std::integer_sequence 中间对象创建的编译时std::array 的大小。)

【问题讨论】:

  • 如果我没记错的话,是的,有一个限制,但它应该比递归实例化限制大几个数量级。

标签: c++ c++11 c++14 constexpr limits


【解决方案1】:

可以在[implimits] ¶2 中找到相关建议:

(2.35) -   递归 constexpr 函数调用 [512]

(2.36) -   在核心常量表达式 [1 048 576]

中计算的完整表达式

GCC 和 Clang 允许通过 -fconstexpr-depth(这是您要查找的标志)进行调整。

常量表达式求值实际上在沙盒中运行,因为undefined behavior must be preempted by the implementation。考虑到这一点,我不明白为什么实现不能使用主机的全部资源。再说一次,我不建议编写编译需要千兆字节内存或其他不合理资源的程序......

【讨论】:

  • 好的,“模板声明中的模板参数 [1 024]”是否也计算参数包的长度? (我猜是的,否则你只能在编写极其糟糕的 C++ 代码时遇到这个限制。)如果是这样,那将意味着构建一个 std::array<uint32_t, 65536> 查找表来一次处理两个字节可能是不切实际的。
  • @DanielSchepler 我不明白。
  • 最后,该表是由一个函数template <uint8_t... I> constexpr std::array<uint32_t, sizeof...(I)> crc_table_impl(uint32_t crc_poly, std::integer_sequence<uint8_t, I...>) { return { crc_table_entry(crc_poly, I)... }; } 创建的,该函数被传递一个包含0到255的integer_sequence。所以,如果我尝试对uint16_t做同样的事情,就会有具有 65537 个参数的中间模板。
  • @DanielSchepler 是的,这是一个奇怪的计划。为什么不直接使用循环?
  • 据我所知,在 constexpr 函数中初始化整数类型的 std::array 的唯一有效方法是从头开始给出所有元素。如果我尝试使用默认构造函数 gcc 错误:uninitialized variable ‘result’ in ‘constexpr’ function(然后继续解释默认构造函数不会初始化数组)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 2021-11-22
相关资源
最近更新 更多