Constexpr 这是正确的行为吗?

Constexpr is this correct behaviour?

我不确定这是正确的行为。所以我之前没有搞砸过 constexpr 并且想确保我没有误解规范的某些内容。按照 MSDN 提到的方式进行测试。如果我在函数中放置一个断点并且它被跳过,那么它会在编译时被评估。行为是否低于正常水平?

https://msdn.microsoft.com/en-us/library/dn956974.aspx

  1. 它似乎只对周期优化有效。
  2. 它仅在我将值设置为 constexpr 变量或在与输入变量无关的特定用例中有效。

所以出于某种原因这有效

constexpr unsigned int factorial(unsigned int n)
{
    return n <= 1 ? 1 : n*factorial(n - 1);
}
constexpr unsigned int value = factorial(5);
std::cout << value << std::endl;

但这在 运行 时间 运行

constexpr unsigned int factorial(unsigned int n)
{
    return n <= 1 ? 1 : n*factorial(n - 1);
}

std::cout << factorial(5) << std::endl;

似乎不​​得不制作一个 constexpr 变量有点不方便。它似乎适用于其他一些特殊情况。

switch (fnv1a("Hello"))
{
case fnv1a("GoodBye"):
    std::cout << "GoodBye" << std::endl;
    break;
case fnv1a("Hello"):
    std::cout << "Hello" << std::endl;
    break;
default:
    break;

}

这种情况将 case 值初始化为常量,但 switch 语句中的调用未评估为 constexpr,并在 运行 时获得 运行。

出于某种原因,相等运算符似乎也可以工作。此示例仅调用一次 fnv1a 以获得动态值。

void isValue(const char* str)
{
    if (fnv1a(str) == fnv1a("Hello"));
    std::cout << "Found it!" << std::endl;
}

我知道 MSVC 在合规性方面存在一些问题,但不根据用例评估为常数而不是输入是否为常数的行为对我来说似乎很奇怪。

您观察到的行为是正确的。 constexpr 函数需要在编译时仅在常量表达式上调用。这包括 constexpr 函数的 return 值用作 constexpr 变量的初始值设定项,或用作非类型模板参数的值的情况。

在所有其他情况下,编译器不需要在编译时计算函数。