Yon*_* Wu 13 c++ compile-time-constant template-meta-programming constexpr
下面的代码合法吗?
template <int N>
class foo {
public:
constexpr foo()
{
for (int i = 0; i < N; ++i) {
v_[i] = i;
}
}
private:
int v_[N];
};
constexpr foo<5> bar;
Run Code Online (Sandbox Code Playgroud)
Clang 接受它,但 GCC 和 MSVC 拒绝它。
GCC 的错误是:
main.cpp:15:18: error: 'constexpr foo<N>::foo() [with int N = 5]' called in a constant expression
15 | constexpr foo<5> bar;
| ^~~
main.cpp:4:15: note: 'constexpr foo<N>::foo() [with int N = 5]' is not usable as a 'constexpr' function because:
4 | constexpr foo()
| ^~~
main.cpp:4:15: error: member 'foo<5>::v_' must be initialized by mem-initializer in 'constexpr' constructor
main.cpp:12:9: note: declared here
12 | int v_[N];
| ^~
Run Code Online (Sandbox Code Playgroud)
如果这种代码没问题,我可以减少很多index_sequences 的使用。
Lig*_*ica 17
在C++20 之前的constexpr上下文中禁止平凡的默认初始化。
我猜,原因是很容易“意外地”从默认初始化的原语中读取,这种行为会给您的程序带来未定义的行为,并且直接禁止具有未定义行为的表达式constexpr(ref)。该语言已被扩展,因此现在编译器必须检查是否发生了这样的读取,如果没有,则应接受默认初始化。编译器需要做更多的工作,但是(如您所见!)对程序员有很大的好处。
本文建议允许在 constexpr 上下文中为平凡的默认可构造类型进行默认初始化,同时继续禁止调用未定义的行为。简而言之,只要不读取未初始化的值,在堆和堆栈分配方案中的 constexpr 中都应该允许此类状态。
从 C++20 开始,v_像你一样离开“未初始化”是合法的。然后你继续分配它的所有元素值,这很棒。
| 归档时间: |
|
| 查看次数: |
839 次 |
| 最近记录: |