How to pass a VLA to a function template?

2019-01-20 16:06发布

I have the following code which could not be complied.

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;
  }
}

What is the proper way to pass the array if the main is something like below.

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);
}

error: no matching function to call to array_ini_1d..............

6条回答
我想做一个坏孩纸
2楼-- · 2019-01-20 16:32
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;
}
查看更多
三岁会撩人
3楼-- · 2019-01-20 16:33

The problem is that variable size arrays are not supported by c++, and is only supported as compilers extension. That means, the standard doesn't say what should happen, and you should see if you can find in compiler's documentation, but I doubt that such corner cases are documented.

So, this is the problem :

int arr[n];

The solution is to avoid it, and use something supported by c++, like for example std::vector.

查看更多
劫难
4楼-- · 2019-01-20 16:37

I don't think the compiler can deduce the size of a variable-length array in a template. Also, don't forget to forward declare f before you use it. Variable-length arrays are a GCC extension and you should get a warning regarding their use.

查看更多
家丑人穷心不美
5楼-- · 2019-01-20 16:46

As you use Variable length array (VLA) (compiler extension), compiler cannot deduce N.

You have to pass it by pointer and give the size:

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);
}

Or use std::vector. (no extension used so). Which seems cleaner:

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);
}
查看更多
Anthone
6楼-- · 2019-01-20 16:48

You may declare your function like this:

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

However, the problem is that when you call the function, the compiler won't deduce the template parameters, and you will have to specify them explicitly.

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;
}

Unfortunately, that ruins the very idea...

UPD: And even that code does NOT work for an array that has variable length, for the length is calculated at runtime, and the template parameters are defined at compilation time.

UPD2: If using std::vector you may create it initialized: vector<int> arr(n, 0); Or you may fill it with fill from <algorithm> when needed: std::fill(arr.begin(), arr.end(), 0);

查看更多
聊天终结者
7楼-- · 2019-01-20 16:48

Template parameters must be resolved at compile-time.

There is no way that a function template with parameter size_t N can match any sort of array or other container whose size comes from a run-time input.

You will need to provide another version of the array_1d_ini which does not have the size as a template parameter.

查看更多
登录 后发表回答