【问题标题】:constexpr member function of non constexpr constructible class非 constexpr 可构造类的 constexpr 成员函数
【发布时间】:2016-10-29 18:59:59
【问题描述】:

如果非literal 类类型没有constexpr 构造函数(它不是constexpr 可构造函数),那么非静态constexpr 成员函数是否有意义?我的意思是如果你不能在编译时构造对象,你将如何使用它的成员函数?

反正各大编译器都不抱怨,这让我觉得是标准允许的。

不过,您可以在运行时使用此类constexpr 成员函数,而不会出现任何问题。现在唯一的问题是constexpr 在这种情况下的作用是什么,如果有的话。 我的最佳猜测是 constexpr 成员的返回值是在编译时评估的(如果可能的话),所以在运行时调用它必须做一个简单的复制。 p>

我的猜测是正确的,还是 constexpr 说明符在这种情况下绝对没有意义(即成员函数在运行时被评估)?

【问题讨论】:

  • 我对@9​​87654329@ 了解不多,但你的前提和猜测对我来说都是合理的。
  • 您可能需要改写您的问题以专注于非文字类类型。例如,聚合没有 constexpr 构造函数,但拥有 constexpr 成员函数的聚合是有意义的。
  • 同理,如果你只提供私有构造函数(没有任何类型的工厂),你将无法使用非静态的公共方法。
  • @Jarod42 您可以在运行时使用此类constexpr 定义的函数,但尚不清楚在这种情况下constexpr 的预期效果是什么(如果有的话)。
  • 如果你把constexpr这个词去掉,你的粗体字仍然是正确的。

标签: c++ language-lawyer constexpr


【解决方案1】:

您问题的前提似乎是只有constexpr 函数可以在编译时进行评估。

这个前提是不正确的。只要产生确切的副作用和副作用(as-if rule),编译器就可以预先计算任何它可以找到的方法。

constexpr 提供的是保证某些表达式将在编译时由 每个 编译器评估(这不是“实现质量”问题),这使得使用它们成为可能在需要编译时值的上下文中,例如非类型模板参数、switch 语句中的case 子句的操作数等。

围绕constexpr 函数的具体细节包括必须至少有一组参数(目标实例是隐含参数)才能满足constexpr 评估规则。如果不是这样,则您的程序格式错误,并且根本没有指定其运行时行为,因此请不要在逻辑上不属于的地方添加 constexpr

但是,编译器不需要诊断违反此规则的情况。这意味着“主要编译器不会抱怨它”不应以任何方式解释为保证代码正确。


标准的措辞,第 7.1.5 节(草案 n4582)

对于既不是默认值也不是模板的constexpr 函数或constexpr 构造函数,如果不存在参数值,则函数或构造函数的调用可以是评估的子表达式 核心常量表达式,或者,对于构造函数,某个对象的常量初始化器,程序格式错误;无需诊断。

【讨论】:

  • 我的问题没有假设只有 constexpr 函数可以在编译时进行评估。
  • 这是否意味着template <typename T> struct A { constexpr T val() { return T(0); } };template <typename T> struct A { static constexpr T val() { return T(0); } };(第一个没有,第二个有static)也是不正确的?我对这些功能没有任何问题。
  • @placel:这很好,有两个原因:(1)模板函数不受规则约束,(2)在评估constexpr期间不允许的那些函数期间没有执行任何操作处理。
  • @plasmacel:这是一个更好的例子:struct S { int i; S(j) : i{j} {} constexpr int foo() { return i; } constexpr int bar(int k) { return k? i: 0; } }; 其中foo 格式错误,但bar 是合法的,因为o.bar(0); 不会进行任何禁止操作。
  • @plasmacel:另外,您评论中的两种类型是文字类型,因此它们与您的问题无关。
猜你喜欢
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 2020-03-10
  • 2023-03-25
  • 2013-12-24
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
相关资源
最近更新 更多