【问题标题】:C++14: Initializing constexpr variables from parameter valuesC++14:从参数值初始化 constexpr 变量
【发布时间】:2015-10-21 06:43:57
【问题描述】:

假设我有一个可以通过constexpr 函数返回常量表达式的类:

template<int N>
struct Foo {
  constexpr int Bar() const { return N; }
};

如果我想从Foo::Bar() 初始化constexpr 值,我应该如何传递Foo 类型的参数?我已经尝试了这两个,每个内部都有一个示例 constexpr 变量来测试它是否可以初始化:

template<int N>
constexpr int ByValue(Foo<N> f) {
  constexpr int i = f.Bar();
  return f.Bar();
}

template<int N>
constexpr int ByReference(const Foo<N> &f) {
  constexpr int i = f.Bar();
  return f.Bar();
}

constexpr int a = ByValue(Foo<1>{});
constexpr int b = ByReference(Foo<1>{});

但是 clang 3.7 会在 ByReference 上引发错误,而 gcc >=5.1 不会:Live demo

main.cpp:15:25: error: constexpr variable 'i' must be initialized by a constant expression
      constexpr int i = f.Bar();
                        ^~~~~~~
main.cpp:22:25: note: in instantiation of function template specialization 'ByReference<1>' requested here
      constexpr int b = ByReference(Foo<1>{});

Barconstexpr 并返回有效的常量表达式时,采用const Foo &amp; 或普通Foo 有什么区别?

GCC 还是 Clang,哪个是正确的,为什么?如果可以,请参考该标准。

【问题讨论】:

  • 在标准的枚举中有一些关于引用的愚蠢语言可以为您提供编译时常量表达式。显然,clang 学究式地尊重该语言,而 g++ 更实际地忽略了它。希望它会得到修复,但我不记得看到任何关于它的缺陷报告。结果:这是一个灰色地带,并且可能继续是一个。使用宏定义通用数组大小​​函数,只是为了安全起见。
  • 您需要将您的成员函数设为static,这样它就不会依赖于隐式的this 指针,并且可能会取消自己成为常量表达式的资格。
  • 我现在没有时间给出答案,但这类似于this question
  • 我在the FAQ on arrays 中添加了关于数组大小问题的部分,现在是 5.4。请注意@Columbo,由于他在这里的论点(现已删除):FAQ 的这一部分最初是由我编写的。你可以了解所有关于这个和那个的危险。 ;-)

标签: c++ gcc clang c++14 constexpr


【解决方案1】:

§5.20:

i 的角度来看,该引用没有前面的初始化,但是:它是一个参数。一旦调用ByReference,它就会被初始化。

让我们从i 的声明中删除constexpr,并考虑完整地调用ByReference

template<int N>
constexpr int ByReference(const Foo<N> &f) {
    int i = f.Bar();
    return i;
}

constexpr int j = ByReference(Foo<0>());

这很好,因为f 确实有前面的初始化。 f 的初始化器也是一个常量表达式,因为在这种情况下,隐式声明的默认构造函数是 constexpr(第 12.1/5 节)。
因此i 由一个常量表达式初始化,而调用本身就是一个常量表达式。

【讨论】:

  • @Walter No. Clang 拒绝它,因此它是正确的。按照目前的规则,就是这样。
  • 我是这个截图/高亮引用方法的粉丝。 +1!
  • @Barry 是的,我认为这比我在 Markdown 中创建表格的尝试更容易理解;-)
  • @Columbo 因为盲人也访问该网站。
  • @Rakete1111 我已经提交了editorial issue,有人指出这已经是core language issue
猜你喜欢
  • 2019-12-14
  • 1970-01-01
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 2018-04-27
相关资源
最近更新 更多