来自这个问题: How to build a custom macro that behaves differently when used as constexpr (like assert)?
我想知道为什么有条件的话可以调用非constexpr函数。
void bla( )
{
std::cout << "bla called!" << std::endl;
}
constexpr bool check(bool condition)
{
//bla(); // can not directly be called -> not constexpr!
condition ? void (0) : bla(); // compiles and runs even if condition is true or false!
// if condition is const, it did not compile because it
// directly force execution of non constexpr function
true ? void(0): bla(); // also that compiles!, ok, directly evaluated
//true ? bla(): void(0); // that did not compile;)
//false ? void(0): bla(); // that did not compile;)
false ? bla(): void(0); // compiles, ok, directly evaluated
return 0;
}
int main()
{
check( false );
check( true );
}
有人可以解释标准中给出的规则吗? 正如W.F所述:如果结果用于constexpr术语,如 模板参数,如果条件导致评估,则失败 非constexpr功能。
这使assert
在编译结果时直接投诉
用于constexpr术语。
答案 0 :(得分:2)
constexpr
函数意味着可以在编译时评估函数的值。由于输入true
可以使用,因此该函数是有效的constexpr
。请记住,constexpr
函数可以将地址作为常规函数,它不需要是编译时间,只有当用作编译时函数时(在您的示例中不是这样)。
正如cppreference上的constexpr
页面所述:
constexpr函数必须满足以下要求:
- 一定不能虚拟
- 其返回类型必须为LiteralType
- 其每个参数必须为LiteralType
- 至少存在一组参数值,这样函数的调用可以是核心常量表达式的计算子表达式(对于构造函数,在常量初始化器中使用就足够了)(因为C ++ 14) )。违反此项目不需要诊断。 (强调我的)
您的函数满足以上所有要求:它不是虚拟的,它返回文字类型,参数是文字。更有趣的是,最后一个要点:至少存在一组参数值,其函数实际上是完全编译时间。 (因此我强调了最后一颗子弹)
作为W.F.在注释中提到,该函数可以用于编译时,但仅用于有效输入,即不会导致不是编译时常量的子表达式的输入。因此输入true
将起作用,但false
不会,因为它会导致bla
被评估。
标准中也说明了这一点:§10.1.5.5:
对于既不是默认也不是模板的constexpr函数或constexpr构造函数,如果不存在参数值,则函数或构造函数的调用可以是核心常量表达式的评估子表达式(8.20),或者对于构造函数,某个对象的常量初始化程序(6.6.2),程序格式错误,无需诊断。
constexpr int f(bool b) { return b ? throw 0 : 0; } // OK constexpr int f() { return f(true); } // ill-formed, no diagnostic required
特别参见标准文件中的例子。