用于强制constexpr功能的constexpr-ness的惯用方法

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)

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

Yak*_*ont 2

template<auto x>
std::integral_constant< std::decay_t<decltype(x)>, x > k{};
Run Code Online (Sandbox Code Playgroud)

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

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

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