强制 constexpr 函数的 constexpr 的惯用方法

Idiomatic way to enforce constexpr-ness of constexpr functions

本文关键字:constexpr 方法 强制 函数      更新时间:2023-10-16

请考虑以下示例代码:

#include <tuple>
void blah();
int buh;
constexpr auto get() 
{ 
return std::get<0>(std::make_tuple(&blah, &buh));
}
int main()
{
get();
}

人们会期望,由于函数get()是一个常量表达式,它将返回一个常量。

事实并非如此:std::make_tuplestd::get被实例化并调用:https://godbolt.org/g/PkHrTp

现在,如果我们get()

constexpr auto get() 
{ 
constexpr auto x = std::get<0>(std::make_tuple(&blah, &buh));
return x;
}

我们得到预期的行为:参数x的计算被优化出来,即使在-O0和make_tupleget没有实例化,这对于减少二进制膨胀是相当有用的。

有没有一种惯用的方法来强制表单的功能始终像第二个示例中constexpr auto foo()行为?

现在我会求助于:

#define constexpr_return(X) do { constexpr auto constexpr_return_x_ = X; return constexpr_return_x_; } while(0)
constexpr_return(std::get<0>(std::make_tuple(&blah, &buh)));

例如,但我不知道这是否是最佳的。

template<auto x>
std::integral_constant< std::decay_t<decltype(x)>, x > k{};

非类型模板参数实际上必须在编译时计算。

k<get()>或在某些极端情况下,k<get()>()可能会做你想做的事。

这不适用于不能作为非类型模板参数传递constexpr值,但它确实适用于整数、指针和函数指针。