constexpr double f(bool b)
{
return b? 42:42/(rand()+1); // how pure is rand ;)
}
我的问题是标准允许这是什么原因。由于我是参考透明度的忠实粉丝,我希望他们有充分的理由:)我想知道。
BT有相关的Q但是大多数A甚至都不提纯东西,或者当他们这样做时,他们没有指明为什么std允许这个的原因。 Relation between constexpr and pure functions答案 0 :(得分:9)
在标准中,相关要求隐藏在constexpr
函数的主要要求列表下方。它在§7.1.5/ 5中:
对于constexpr函数,如果不存在函数参数值,使得函数调用替换将产生常量表达式(5.19),则程序格式错误;无需诊断。
§5.19定义了常量表达式的要求,因此您无法调用rand()
。
宽松限制允许您拥有条件纯净的功能。您的示例f(true)
是有效的模板参数,但f(false)
不是。
当然,缺点是编译器不会验证constexpr
函数是否可以实际用于其预期目的。你需要编写测试用例。
答案 1 :(得分:7)
函数定义中的关键字constexpr
告诉编译器,如果所有参数和变量在编译时本身已知,则此函数可以在编译时执行。但是,没有这样的保证,例如,当某些值在运行时只能 时,在这种情况下该函数将在运行时执行。
但是,它与 pure 或 impure 无关,因为这些术语暗示输出仅取决于输入,无论您调用多少次具有相同输入参数值的函数,每次输出都是相同的,无论是在编译时还是在运行时计算。
实施例,
constexpr int add(int a, int b) { return a + b; } //pure!
const int a = 2, b = 3; //const
int c = 2, d = 3; //non-const
//we may read update c and d here!
const int v1 = add(2,3); //computed at compile-time
const int v2 = add(a,3); //computed at compile-time
const int v3 = add(2,b); //computed at compile-time
const int v4 = add(a,b); //computed at compile-time
const int v3 = add(c,3); //computed at runtime
const int v3 = add(c,b); //computed at runtime
const int v3 = add(a,d); //computed at runtime
const int v3 = add(c,d); //computed at runtime
请注意,此处add
是纯函数,无论它是在编译时还是在运行时计算。
答案 2 :(得分:6)
因为对于某些输入参数域,永远不会采用不纯的路径。对于该域名,constexpr将正常工作。
例如,您的函数可能有一个简单的分支和一个更复杂的分支。并且您可以指定为了使函数在常量表达式中可用,函数参数必须满足此条件和条件,从而屈服于函数中始终纯粹的简单分支。
有用的副作用是在常量计算期间可能导致错误。即如果违反了简单分支中的前提条件,则可能导致对不纯表达式的求值,引发编译时错误(断言或异常在这里是一个好主意,因为当在一个函数中调用该函数时它继续抱怨运行时上下文)。