有没有办法强制执行std :: array的完全初始化

alf*_*lfC 9 arrays initialization c++11 stdarray

我正在使用std::array<size_t, N>(N是一个固定的模板变量).

#include<array>
template<size_t N>
struct A{
   size_t function(std::array<size_t, N> arr){ return arr[N-1];} // just an example
};

int main(){
   A<5> a;
   a.function({{1,2,3,4,5}}));
}
Run Code Online (Sandbox Code Playgroud)

它工作正常.问题是这个其他代码是默默允许的:

   A.function({{1,2,3}}));
Run Code Online (Sandbox Code Playgroud)

也就是说,即使错过了元素,也会以array某种方式初始化,即使它被很好地定义(例如,剩余元素初始化为零,我不确定)这可能是错误的来源.

有没有办法强制执行额外元素的初始化?例如,通过生成编译器错误或警告.

我想到的一个选择是使用 initializer_list

   size_t function2(std::initializer_list<size_t> il){ assert(il.size() == N); ...}
Run Code Online (Sandbox Code Playgroud)

问题是,这最多会产生运行时错误并检查每次调用.我更喜欢编译器错误/警告.

我没有受到默认初始化的困扰,std::array<>{}而是由不完整的初始化所困扰.(也许没有什么可以做的,因为这是从T[N]静态数组的行为继承而来的.)

我试过用clang 3.5gcc 5.

Sta*_*tas 5

您可以使用参数包来强制执行此操作,但语法略有不同:

#include <array>

template<size_t N>
struct A{
   template<typename... T>
   size_t function(T&&... nums)
   {
     static_assert(sizeof...(nums) == N, "Wrong number of arguments");
     std::array<size_t, N> arr = { std::forward<size_t>(nums)... };
     return arr[N-1];
   }
};

int main(){
   A<5> a;
   a.function(1,2,3,4,5); // OK
   a.function(1,2,4,5);   // Compile-time error
}
Run Code Online (Sandbox Code Playgroud)

但是,我认为没有好的方法可以在编译时强制执行。我只会assert(il.size() == N)在生产代码中使用来检查初始化列表的大小。


tex*_*uce 2

简单的回答:你不能。

std::array当用列表初始化时,它正在做一个,当列表大小小于成员数量时,这里aggregate initialization解释一下:

  • 如果初始化子句的数量小于成员的数量或初始化列表完全为空,则其余成员将通过其大括号或等号初始化器进行初始化(如果在类定义中提供),否则(C++14 起)通过空列表,执行值初始化。如果引用类型的成员是这些剩余成员之一,则程序格式错误(引用不能进行值初始化)

提供小于大小列表只是一种合法且可接受的行为,因此编译器不会抱怨任何事情。你的代码:

A<5> a;
a.function({{1,2,3}}));
Run Code Online (Sandbox Code Playgroud)

相当于:

A<5> a;
a.function({{1,2,3,0,0}}));
Run Code Online (Sandbox Code Playgroud)

到编译器。你最好的选择是运行时错误(这可能不是你想要的)。