constexpr 条件不是常量?

constexpr condition not constant?

我写了下面的 C++17 代码:

constexpr bool gDebug = true;

template <typename T> constexpr const T& Select(const bool pCondition, const T& a, const T& b)
{
   if constexpr (pCondition)
   {
      return a;
   }
   else
   {
      return b;
   }
}

然后我这样称呼它:

int c = Select<QString>(gDebug, a, b); // In .cpp

if constexpr 行得到 error: ‘pCondition’ is not a constant expression

为什么?这行不通吗?

Why? Shouldn't this work?

不,不应该。 pCondition 不是 constant expression。我明白为什么这可能会令人困惑,因为 pConditionconst - 但术语常量表达式指的是它能够在编译时求值。也就是说,不是 const,而是 constexpr

函数参数不是常量表达式。您碰巧传递了编译时常量这一事实并不重要,因为您可以轻松传递从标准输入或其他内容读取的运行时变量。

if constexpr 需要一个常量表达式,所以你真的只需要 if 。或者,您需要将条件提升为常量表达式 - 例如通过将其设为模板参数:

template <bool pCondition, typename T>
constexpr const T& Select(const T& a, const T& b)
{
   if constexpr (pCondition) // now okay
   {
      return a;
   }
   else
   {
      return b;
   }
}

int c = Select<qDebug>(a, b);

或者您可以要求参数是编码为类型的值:

template <typename Boolean, typename T>
constexpr const T& Select(Boolean pCondition, const T&, const T&);

constexpr std::true_type qDebug{}; // true_type, not bool = true
int c = Select(qDebug, a, b);      // okay

Barry 是正确的,但我认为这并不是您理解错误的地方。

template <typename T> constexpr const T& Select(const bool pCondition, const T& a, const T& b)

意味着如果参数是,函数调用在编译时是可评估的。但是可以使用编译时未知的参数调用该函数。在这种情况下,函数调用本身不是常量表达式,将在 运行 时进行计算。尽管在函数式编程的意义上它仍然是纯粹的,顺便说一句,它是 noexcept

if constexpr (pCondition) {... 确实意味着表达式必须在编译时可计算。

因此,由于可以在编译时使用未知参数调用 constexpr 函数,因此它不能包含声明为 constexpr 的表达式(如果它们依赖于这些参数)。

所有其他答案都是正确的,并没有说出我在绊倒这个问题时想知道的事情。对于在 constexpr (compile-time) 和变量(运行时)上下文中工作的 constexpr 函数,正如 Patrick 指出的那样,函数中不能有任何将其限制为 constexpr 上下文的内容。更重要的是,您 不需要 任何此类限制即可使函数在 constexpr 上下文中工作。编译器弄清楚了——它现在可以自由地(根据需要)在 constexpr 或运行时上下文中评估函数。所以if constexpr (pCondition)中的constexpr可以简单的去掉