3

只是想知道-我写了以下功能

template <class T, size_t N>
T* asFlatArray (T arr[][N])
{
    // some code
}

并称它为

asFlatArray(myArray); // where myArray is int myArray[some_size][sime_size];

编译运行没有错误。但是,如果我将“arr”更改为引用

template <class T, size_t N>
T* asFlatArray (T (&arr)[][N])
{
    // some code
}

我会有错误:

parameter ‘arr’ includes reference to array of unknown bound ‘T [][N]’

我知道如何解决它

template <class T, size_t Rows, size_t Columns>
T* asFlatArray (T (&arr)[Rows][Columns])

但我不明白为什么会这样?

4

2 回答 2

5

根本问题是第一个函数模板等价于

template <class T, size_t N>
T* asFlatArray (T (*arr)[N]) {}

所以没有维度可以计算。它将匹配指向数组的指针,或任何可以衰减为指向数组的指针的东西。因此也可以匹配二维数组。

至于第二个例子,类型的引用或指针T[][N]不能是函数参数,这会导致编译器错误。当然,您可以为缺少的维度添加额外的模板参数:

template <class T, size_t N, size_t M>
T* asFlatArray(T (&arr)[N][M]) {}
于 2014-10-12T18:08:23.380 回答
1

C++11 和 C++14 标准部分[dcl.fct]/8 (8.3.5)明确规定:

如果参数的类型包括“指向未知边界数组的指针T”或“对未知边界数组的引用”形式的类型,T则程序是非良构的。

实际上有一个核心语言活动问题提议从标准中删除它,所以我们可能不会在 C++17 中看到它。

顺便说一句,如果数组大小真的未知,clang(但不是 gcc)会编译代码:

#include <iostream>

class A {
public:
    static int arr[][3];
};

// this compiles on clang but not gcc
void func(int (&arr_ref)[][3]) {
    std::cout << arr_ref[1][2] << std::endl;
}

int main() {
    int (&arr_ref)[][3] = A::arr;

    std::cout << A::arr[1][2] << std::endl;

    arr_ref[1][2] = 100;
    std::cout << A::arr[1][2] << std::endl;

    arr_ref[1][2] = 200;
    func(arr_ref); 
}

int A::arr[][3] = {{1, 2, 3}, {4, 5, 6}};

演示

于 2014-10-12T18:16:54.083 回答