C++14:从参数值初始化 constexpr 变量
C++14: Initializing constexpr variables from parameter values
假设我有一个 class,它可以通过 constexpr
函数 return 一个常量表达式:
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>{});
当 Bar
是 constexpr
并且 return 是有效常量表达式时,采用 const Foo &
或普通 Foo
有什么区别?
GCC 还是 Clang,哪个是正确的,为什么?如果可用,将不胜感激对标准的引用。
§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
由常量表达式初始化,调用本身就是一个常量表达式。
假设我有一个 class,它可以通过 constexpr
函数 return 一个常量表达式:
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>{});
当 Bar
是 constexpr
并且 return 是有效常量表达式时,采用 const Foo &
或普通 Foo
有什么区别?
GCC 还是 Clang,哪个是正确的,为什么?如果可用,将不胜感激对标准的引用。
§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
由常量表达式初始化,调用本身就是一个常量表达式。