C++ 14:从参数值初始化constexpr变量

Xo *_*ang 9 c++ gcc clang constexpr c++14

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

template<int N>
struct Foo {
  constexpr int Bar() const { return N; }
};
Run Code Online (Sandbox Code Playgroud)

如果我想初始化constexpr值Foo::Bar(),我应该如何传递类型的参数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>{});
Run Code Online (Sandbox Code Playgroud)

但是clang 3.7引发了一个错误,ByReference而gcc> = 5.1则没有:现场演示

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>{});
Run Code Online (Sandbox Code Playgroud)

采用a const Foo &或plain 之间的区别是什么Foo,何时Barconstexpr哪种方式并返回有效的常量表达式?

哪个是正确的,为什么,GCC或Clang?如果可用,将赞赏对标准的引用.

Col*_*mbo 6

§5.20:

在此输入图像描述

但是,从引用的角度来看,引用没有先前的初始化i:它是一个参数.它被初始化一次ByReference被调用.

让我们删除constexprfrom i的声明并考虑完整的调用ByReference:

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

constexpr int j = ByReference(Foo<0>());
Run Code Online (Sandbox Code Playgroud)

这很好,因为f确实有先前的初始化.初始化程序f也是一个常量表达式,因为constexpr在这种情况下隐式声明的默认构造函数(第12.1/5节).
因此i,通过常量表达式初始化,并且调用本身是一个常量表达式.

  • @Columbo因为盲人也访问该网站. (3认同)