【问题标题】:Strange behavior with constexpr interacting with const referencesconstexpr 与 const 引用交互的奇怪行为
【发布时间】:2020-12-08 00:26:44
【问题描述】:

我使用 clang 和 gcc(主干版本)测试了以下代码。有人可以解释为什么使用普通 X 结构的情况不起作用,而按值捕获和使用 const 引用的包装情况都可以正常工作。

struct X {
  constexpr X(const int &v) : x(v) {}
  constexpr int Get() const { return x; }
private:
  const int& x;
};

constexpr X f(const X& r) {
  return r;
}

struct Y {
  constexpr Y(const int &v) : x(v) {}
  constexpr int Get() const { return x; }
private:
  const int x;
};

constexpr Y f(const Y& r) {
  return r;
}

struct Wrap {
  constexpr Wrap(const int& v) : x(v) {}
  constexpr Y Get() const { return Y{x}; }
private:
  const int x;
};


int main() {
  constexpr const int x = 10;

  /* this does not work for some reason 
  constexpr X a(x);
  static_assert(f(a).Get() == 10, "This should work.");
  */

  // This works.
  constexpr Y b(x);
  static_assert(f(b).Get() == 10, "This should work.");

  // This also works.
  constexpr Wrap c(x);
  static_assert(f(c.Get()).Get() == 10, "This should work.");

  return 0;
}

【问题讨论】:

    标签: c++ constexpr c++20


    【解决方案1】:

    你在这里违反的规则:

    constexpr X a(x);
    

    consetxpr 指针或constexpr 引用是否必须引用具有静态存储持续时间的对象 - 这是其自身地址成为常量表达式的唯一方法。 不是x 的情况。

    但是一旦你做到了(const 是多余的):

    static constexpr int x = 10;
    

    然后剩下的工作:

    constexpr X a(x);
    static_assert(f(a).Get() == 10, "This should work.");
    

    具体规则为[expr.const]/11:

    常量表达式要么是一个泛左值核心常量表达式,它引用一个作为常量表达式(如下定义)的允许结果的实体,要么是一个纯右值核心常量表达式,其值满足以下约束:

    • 如果值是类类型的对象,则每个引用类型的非静态数据成员都引用一个实体,该实体是常量表达式的允许结果,

    [...]

    实体是常量表达式的允许结果,如果它是具有静态存储持续时间的对象,要么不是临时对象,要么是其值满足上述约束的临时对象,或者如果它是一个非立即函数。


    另请参阅 these answersmine。我可能应该把所有这些都当作其中之一的骗子来关闭?

    【讨论】:

    • 确实如此:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    相关资源
    最近更新 更多