Jea*_*ier 6 c++ constexpr c++11 c++14 c++17
请考虑以下示例代码:
#include <tuple>
void blah();
int buh;
constexpr auto get()
{
return std::get<0>(std::make_tuple(&blah, &buh));
}
int main()
{
get();
}
Run Code Online (Sandbox Code Playgroud)
人们可以预期,由于函数get()
是一个常量表达式,它将返回一个常量.
这不是发生的事情:std::make_tuple
,std::get
实例化并调用:https://godbolt.org/g/PkHrTp
现在,如果我们替换get()
by 的实现
constexpr auto get()
{
constexpr auto x = std::get<0>(std::make_tuple(&blah, &buh));
return x;
}
Run Code Online (Sandbox Code Playgroud)
我们得到了预期的行为:该参数x
的计算是优化掉了,甚至在-O0,并且make_tuple
,get
没有实例化,它可以是相当有用的,以减少二进制膨胀.
是否有一种惯用的方式来强制表单的功能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)));
Run Code Online (Sandbox Code Playgroud)
例如,但我不知道这是否是最佳的.
template<auto x>
std::integral_constant< std::decay_t<decltype(x)>, x > k{};
Run Code Online (Sandbox Code Playgroud)
实际上必须在编译时评估非类型模板参数。
k<get()>
或者在某些极端情况下k<get()>()
可能会做你想要的事情。
这不适用于constexpr
无法作为非类型模板参数传递的值,但它适用于整数、指针和函数指针。