gpt4 book ai didi

c++ - 为什么我们需要将函数标记为constexpr?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:53:28 29 4
gpt4 key购买 nike

C++ 11允许使用constexpr说明符声明的函数在常量表达式(例如模板参数)中使用。关于constexpr的允许有严格的要求;本质上,这样的函数只封装一个子表达式,而没有其他封装。 (编辑:这在C++ 14中放松了,但问题仍然存在。)

为什么根本需要关键字? 获得了什么?

它确实有助于揭示接口(interface)的意图,但它doesn't通过保证函数可在常量表达式中使用来验证该意图。编写constexpr函数后,程序员必须仍然:

  • 编写一个测试用例,或者确保它在常量表达式中实际使用。
  • 记录在常量表达式上下文中哪些参数值有效。

  • 与揭示意图相反,使用 constexpr修饰功能可能会增加错误的安全感,因为在忽略中心语义约束的同时检查了切向句法约束。

    简而言之:如果函数声明中的 constexpr仅是可选的,会对语言产生不良影响吗?还是对任何有效程序完全没有影响?

    最佳答案

    防止客户端代码期望超出预期
    假设我正在编写一个库,并且那里有一个函数,该函数当前返回一个常量:awesome_lib.hpp:

    inline int f() { return 4; }
    如果不需要 constexpr,您-作为客户端代码的作者-可能会离开并执行以下操作: client_app.cpp:
    #include <awesome_lib.hpp>
    #include <array>

    std::array<int, f()> my_array; // needs CT template arg
    int my_c_array[f()]; // needs CT array dimension
    然后,如果我更改 f()以说从配置文件返回该值,则您的客户端代码将被破坏,但是我不知道有冒险破坏您的代码的危险。确实,只有在您遇到一些生产问题并进行重新编译时,您才会发现此附加问题使重建工作受挫。
    通过仅更改 f()的实现,我将有效地更改可以对接口(interface)进行的使用。
    相反,C++ 11起提供 constexpr,因此我可以表示客户端代码可以对保留 constexpr的函数抱有合理的期望,并按原样使用它。我知道并认可此类用法作为界面的一部分。就像在C++ 03中一样,编译器继续保证不会将客户端代码构建为依赖于其他非 constexpr函数,以防止上述“不必要/未知的依赖关系”场景;不仅仅是文档-它是编译时间执行。
    值得注意的是,这延续了C++的趋势,即为预处理器宏的传统用法提供更好的替代方法(考虑 #define F 4,以及客户端程序员如何知道lib程序员是否将其改为 #define F config["f"]认为是公平的游戏),并带有众所周知的“邪恶”例如位于语言的 namespace /类范围界定系统之外。
    为什么没有针对“显然”的永不常量函数的诊断程序?
    我认为这里的困惑是由于 constexpr没有主动确保存在任何参数的结果实际上是编译时const:相反,它要求程序员对此负责(否则,第7.1.5 / 5节) Standard认为程序格式错误,但不需要编译器发出诊断信息。是的,这很不幸,但是并没有删除上面的 constexpr实用程序。
    因此,将问题从“ constexpr的要点”切换为考虑“为什么我要编译一个从不实际返回const值的 constexpr函数?”也许是有帮助的。
    答案:因为需要详尽的分支分析,其中可能涉及许多组合。诊断的时间和/或编译成本可能过高,甚至超出了任何可以想象的硬件的能力。此外,即使在实际中必须准确诊断此类情况,对于编译器编写者(他们的时间使用得更好)来说,蠕虫也可以使用全新的工具。程序也将产生一些影响,例如在执行验证时需要显示从 constexpr函数中调用的函数(以及调用函数的函数等)。
    同时,缺少 constexpr仍然禁止将其用作const值:严格性在sans constexpr方面。如上所述,这很有用。
    与非`const`成员函数的比较
  • constexpr阻止int x[f()],而缺少const阻止const X x; x.f();-它们都是,以确保客户端代码不会硬编码不需要的依赖项
  • 在两种情况下都是
  • ,即,您不希望编译器自动确定const[expr] -ness :
  • ,当您已经可以预料到该函数将演变为修改可观察值,从而破坏客户端代码时,您不希望客户端代码调用const对象上的成员函数
  • 如果您已经期望以后在运行时确定它,那么您就不想将其用作模板参数或数组维度

  • 它们不同,在于编译器在const成员函数中强制使用其他成员的const使用,但不对constexpr强制执行编译时常量结果(由于实际的编译器限制)
  • 关于c++ - 为什么我们需要将函数标记为constexpr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24099064/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com