我使用__builtin_expect
在constexpr函数中执行空指针检查,如下所示:
constexpr int Add(const int * x, const int * y)
{
assert(__builtin_expect(!!(x && y), 1));
return *x + *y;
}
我也有一个const ref的包装器方法,允许传递临时变量:
constexpr int Add(const int & x, const int & y)
{
return Add(&x, &y);
}
然后使用临时变量创建一个全局常量:
static constexpr int result = Add(1, 2);
打印此值将得到0
:
int main() {
std::cout << result; // 0
}
这到底是怎么回事?
删除__builtin_expect
无法编译,GCC抱怨指针比较到constexpr上下文中的临时变量可能与此相关。
Godbolt
这是一个编译器错误,特别是https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85944.
问题与__builtin_expect
无关。它是关于常量表达式上下文中的空指针检查本身。应该没问题。在作为常量表达式求值期间,编译器知道指针引用的是临时对象,其生存期跨越常量表达式求值期间,因此不为空。满足Add(1, 2)
为核心常数表达式的所有条件
但是GCC似乎不能正确处理命名空间范围内的临时信息。如果将result
设置为块作用域变量(无论是否包含static
),则一切都按预期工作。
constexpr
变量中,然后传递给Add
。将初始化式包装在lambda中以引入块作用域可能也会很好:
static constexpr int result = []{ return Add(1, 2); }();