【发布时间】:2018-05-24 21:32:28
【问题描述】:
考虑以下示例代码:
#include <tuple>
void blah();
int buh;
constexpr auto get()
{
return std::get<0>(std::make_tuple(&blah, &buh));
}
int main()
{
get();
}
人们会认为,由于函数 get() 是一个常量表达式,它会返回一个常量。
事实并非如此:std::make_tuple、std::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_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)));
例如,但我不知道这是否最佳。
【问题讨论】:
-
我建议不要直接询问“另一个库”。虽然要求图书馆推荐可能被认为是题外话,但如果没有这一部分,这个问题似乎非常有价值。
-
值得指出的是,即使在-O1,一切都消失了。我不希望您的担忧经常成为问题。如果是这样,那段代码就可以重写。
-
在编译选项中添加
-O3。 -
查看未优化的程序集确实没有帮助。即使在 -O1 处,所有代码都被优化掉了:godbolt.org/g/ExKyML
-
顺便说一句,
constexpr auto a = get();甚至会删除对get()的调用(两个版本)。
标签: c++ c++11 c++14 c++17 constexpr