我怎么知道编译器是否C++编译时计算表达式
How can I know if C++ compiler evaluates the expression at compile time?
我有这样的代码
const int Value = 123 * 2 + GetOffset();
GetOffset
是一个返回int
的constexpr
函数。
如何确保在编译时确实计算了此表达式?
你为什么不把constexpr
也用于价值?我认为它会要求编译器对其进行评估,
constexpr int Value = 123 * 2 + GetOffset();
如果函数 GetOffset(( 很简单并且满足 constexpr
的要求。
要求是
该函数必须具有非 void 返回类型。
函数体不能声明变量或定义新类型。
正文只能包含声明、NULL 语句和单个返回陈述。
由于Getoffset()
返回int
,它满足了第一个。
您无法确保编译器执行此操作。通常需要启用优化,包括某种级别的函数内联。这些选项是什么取决于您的编译器及其版本。
可以检查生成的程序集,以查看它是否包含对GetOffset
的调用或仅使用编译器确定的常量。
如果你也声明"Value"为constexpr怎么办?实际上,您永远无法确定是否在编译时评估了某些内容,但是在这种情况下,没有理由无法对其进行评估。
一种可能性是使用 std::ratio
。 从 C++11 标准的第 20.10.1 节:
此子子句描述比率库。它提供了一个类模板比率,该比率精确地表示任何有限有理数,分子和分母可由 intmax_t 类型的编译时常量表示。
因此,根据标准,这仅对编译时常量有效:
const int value = std::ratio<123 * 2 + GetOffset()>::num;
因此,这将保证在编译时计算表达式。 但是,它也不能保证在运行时不计算表达式。
你不能绝对确定;编译器只需要生成具有指定行为的代码,在编译或运行时计算它不会改变行为。
但是,编译器需要能够在编译时对此进行评估,因为它可以在只允许编译时常量(如数组大小和模板参数(的情况下使用;因此,理智的编译器没有理由不执行明显的优化。如果编译器没有(至少在启用优化的情况下(,请将其丢弃并找到更好的编译器。
您可以检查编译器生成的程序集,以查看它是否计算值;但这本身并不能保证将来的构建也会这样做。
考虑到我已经五年多没有使用C++了,建议成为标记方式的可能性很高,但是使用内联函数呢?
如果函数返回在编译时可用的某个预定义值,则编译器应该能够使用该值。
使用表达式创建单独的源文件。评估printf("#define MyExpression %d.n", expression);
。生成项目时,请为本机系统编译此源文件并执行它。将生成的输出作为标头包含在常规源中。
如果要确认初始值设定项是常量表达式,则可以使用constexpr
说明符:
constexpr int Value = 123 * 2 + GetOffset();
如果它不是常量表达式,则编译失败。
理论上没有指定 constexpr 变量Value
是否在翻译过程中实际计算 - 但在实践中您可以确定它是。
只是断言它:static_assert(Value == 123 * 2 + GetOffset(), "constexpr");
没有比这更简单
- (C++)分析树以计算返回错误值的简单算术表达式
- 断言中的Fold表达式在某些计算机上编译,但在其他计算机上不编译
- 如何计算具有指定类型的表达式的相对精度和绝对精度
- 编译器是否强制根据模板参数计算表达式?
- 为什么'typeid(x) == typeid(y)'的计算结果为 true,其中 'x' 和 'y' 分别是 T 和 T& 类型的 id-表达式?
- 如何在常量计算表达式中获取编译时错误?
- 计算表达式字符串由 std::map 中的键组成
- GDB 如何在运行时计算C++表达式
- 从C++调用 Python 或 Lua 来计算表达式,仅在需要时计算未知变量
- 错误指针:解析令牌时无法计算表达式
- 在c++lldb中使用重载运算符计算表达式
- 在不使用函数 pow 的情况下计算表达式的总和
- 使用 std::map<std::string, int> 计算表达式树
- 我怎么知道编译器是否C++编译时计算表达式
- BSTR bstrRtf = 0xcccccccccccccccc <调试时错误 Ptr>( = CXX0030:错误:无法计算表达式)
- 正在计算表达式C++
- CXX0030:错误:无法计算表达式
- 计算表达式
- 为什么c++应用程序可能不正确地计算表达式
- char*中的C++错误PTR(无法计算表达式)