0

我编写了以下 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

error: ‘pCondition’ is not a constant expressionif constexpr电话。

为什么?这不应该工作吗?

4

2 回答 2

5

为什么?这不应该工作吗?

不,不应该。pCondition不是常量表达式。我可以理解为什么这可能会令人困惑,因为pConditionis const- 但是术语常量表达式是指它能够在编译时进行评估。也就是说,不是,const而是真的constexpr

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

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
于 2018-12-03T18:13:24.347 回答
1

巴里是正确的,但我认为这并不是你理解错误的地方。

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

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

if constexpr (pCondition) {...实际上意味着表达式必须在编译时可评估。

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

于 2018-12-03T19:13:08.537 回答