如何将 VLA 传递给函数模板

How to pass a VLA to a function template?

本文关键字:函数模板 VLA      更新时间:2023-10-16

我有以下代码无法遵守。

using namespace std;
void f(int);
template<typename T1, size_t N>
void array_ini_1d(T1 (&x)[N])
{
  for (int i = 0; i < N; i++)
  {
    x[i] = 0;
  }
}

如果 main 如下所示,传递数组的正确方法是什么。

int main()
{
  int a;
  cin >> a;
  int n = a / 4;
  f(n);
  return 0;
}
void f(int n)
{
  int arr[n];
  array_ini_1d(arr);
}

错误:没有匹配函数可以调用array_ini_1d.............。

我认为编译器无法推断模板中可变长度数组的大小。另外,不要忘记在使用之前转发声明f。可变长度数组是 GCC 扩展,您应该收到有关其使用的警告。

问题是 c++ 不支持变量大小数组,仅支持作为编译器扩展。这意味着,标准没有说明应该发生什么,你应该看看你是否可以在编译器的文档中找到,但我怀疑这种极端情况是否被记录下来。

所以,这就是问题所在:

int arr[n];

解决方案是避免它,并使用 c++ 支持的东西,例如 std::vector .

当您使用可变长度数组 (VLA)(编译器扩展)时,编译器无法推断 N。

您必须通过指针传递它并给出大小:

template<typename T>
void array_ini_1d(T* a, std::size_t n)
{
    for (std::size_t i = 0; i != n; ++i) {
        a[i] = 0;
    }
}
void f(int n)
{
    int arr[n];
    array_ini_1d(arr);
}

或使用std::vector.(没有使用扩展名)。哪个看起来更干净:

template<typename T>
void array_ini_1d(std::vector<T>& v)
{
    for (std::size_t i = 0, size = v.size(); i != n; ++i) {
        a[i] = 0; // or other stuff.
    }
}
void f(int n)
{
    std::vector<int> arr(n); // or arr(n, 0).
    array_ini_1d(arr);
}
你可以

像这样声明你的函数:

template <typename A, size_t N> void f(A a[N]) {
    for(size_t i = 0; i < N; i++)
        cout << a[i];
}

但是,问题是,当您调用该函数时,编译器不会推断模板参数,您必须显式指定它们。

char arr[5] = {'H', 'e', 'l', 'l', 'o'};
int main()
{
    //f(arr); //Won't work
    f<char, sizeof(arr)/sizeof(arr[0])>(arr);
    cout << endl;
    return 0;
}

不幸的是,这破坏了这个想法...

UPD:即使该代码也不适用于具有可变长度的数组,因为长度是在运行时计算的,模板参数是在编译时定义的。

UPD2:如果使用std::vector您可以创建初始化它: vector<int> arr(n, 0);或者,您可以在需要时用<algorithm>中的fill填充它: std::fill(arr.begin(), arr.end(), 0);

模板参数必须在编译时解析。

具有参数 size_t N 的函数模板无法匹配大小来自运行时输入的任何类型的数组或其他容器。

您需要提供另一个版本的array_1d_ini,该版本没有大小作为模板参数。

template<typename T, size_t N>
void f(T* a)
{
/* add your code here */
}
int main()
{
    int a[10];
    f<int, 10>(a);
    return 0;
}