我编写了以下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 expression
行中得到了if constexpr
。
为什么?这不行吗?
答案 0 :(得分:5)
为什么?这不行吗?
不,不应该。 pCondition
不是constant expression。我知道为什么这可能会造成混淆,因为pCondition
是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
答案 1 :(得分:1)
巴里(Barry)是对的,但我认为这并不是您理解上的错误所在。
template <typename T> constexpr const T& Select(const bool pCondition, const T& a, const T& b)
表示如果参数正确,则函数调用在编译时可求值。但是可以使用非常量参数调用该函数。在这种情况下,函数调用本身不是常量表达式,将在运行时求值。尽管从函数式编程的角度来看,它仍然是纯净的,顺便说一下,它是noexcept
。
但是if constexpr (pCondition) {...
实际上意味着表达式必须在编译时可求值。
因此,由于constexpr函数可以用非const参数调用,因此如果依赖于这些参数,则不能包含声明为constexpr
的表达式。