【问题标题】:Idiomatic way to enforce constexpr-ness of constexpr functions强制执行 constexpr 函数的 constexpr-ness 的惯用方法
【发布时间】: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_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)));

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

【问题讨论】:

  • 我建议不要直接询问“另一个库”。虽然要求图书馆推荐可能被认为是题外话,但如果没有这一部分,这个问题似乎非常有价值。
  • 值得指出的是,即使在-O1,一切都消失了。我不希望您的担忧经常成为问题。如果是这样,那段代码就可以重写。
  • 在编译选项中添加-O3
  • 查看未优化的程序集确实没有帮助。即使在 -O1 处,所有代码都被优化掉了:godbolt.org/g/ExKyML
  • 顺便说一句,constexpr auto a = get(); 甚至会删除对get() 的调用(两个版本)。

标签: c++ c++11 c++14 c++17 constexpr


【解决方案1】:
template<auto x>
std::integral_constant< std::decay_t<decltype(x)>, x > k{};

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

k&lt;get()&gt; 或在某些极端情况下k&lt;get()&gt;() 可能会满足您的需求。

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

【讨论】:

    猜你喜欢
    • 2022-08-17
    • 2019-08-03
    • 2021-04-20
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    相关资源
    最近更新 更多