在D中通过引用传递数组

时间:2015-07-21 17:20:31

标签: d

我正在尝试将数据从matrixA复制到matrixB M,但我收到错误:

app.d(20): Error: function app.M (double[][] s, ref double[][] d, int row, int col) is not callable using argument types (double[5][5], double[][], int, int)

代码:

double matrixA[5][5] = [ [ 1.0, 2.0, 3.0, 4.0, 5.0 ],  
                         [ 1.0, 2.0, 3.0, 4.0, 5.0 ],  
                         [ 1.0, 2.0, 3.0, 4.0, 5.0 ],  
                         [ 1.0, 2.0, 3.0, 4.0, 5.0 ],  
                         [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ];
double matrixB[][];

void M(double[][] s, ref double[][] d, int row, int col)
{
    d.length = row;

    foreach (i; 0 .. d.length)  
        d[i].length = col;

    d = s;
}

void main()
{
    M(matrixA, matrixB, 5, 5);
}

2 个答案:

答案 0 :(得分:1)

你似乎有两个问题。一个ref,一个尝试隐式转换无效。

在D中使用ref时,类型必须完全匹配。隐式转换不会削减它。所以,例如,如果你有

int[5] a = [1, 2, 3, 4, 5];
int[] b = a;

你有

void foo(int[] bar) {}

然后这两行都会编译

foo(a);
foo(b);

因为静态数组会隐式转换为动态数组,但是如果你更改它以便foo通过ref获取其参数

void foo(ref int[] a) {...}

然后

foo(a); // won't compile, because a is int[5], not int[]
foo(b); // compiles, because b is int[]

因此,如果您有一个需要ref double[][]的函数,则必须将double[][]传递给它。隐式转换为double[][]的任何内容都无效。

现在,情况比这更糟糕,因为你传递的是double[5][5],它不会隐式转换为double[][]。因此,即使ref接受了隐式转换,您的代码也无效,即使您删除了ref,您的代码也无效。可以对单维静态数组进行切片(隐式或显式)以获得动态数组,但是您无法对多维静态数组进行切片以获得动态数组。

double[5] a;
double[] b = b; // compiles
double[] c = a[]; // compiles

double[5][5] d;
double[][] e = d; // does not compile
double[][] f = d[]; // does not compile

AFAIK,如果您要将double[5][5]分配给double[][],则必须执行类似

的操作
double[5][5] a;
double[][] b;

foreach(i; row; a)
    b[i] = row[];

最近在支持使用多维切片的用户定义类型方面做了一些工作,因此可以使用我不知道的语法将double[5][5]切换为double[][] ,但它可能只适用于用户定义的类型。无论如何,没有从double[5][5]double[][]的隐式转换,隐式转换不适用于ref

答案 1 :(得分:0)

目前使多维动态数组在静态数组中运行起来有点困难。

要回答您的问题,您可以使用模板定义一个功能:

void M(T)(T s, ref double[][] d, int row, int col) 
  if (is(typeof(s[0][0]) : double))
{ }

此声明表明源s可以是任何类型T,这样在0,0处索引T会返回一个double(或者可以隐式转换为double的内容。

但是,您的功能体将无法正常显示。当它们的大小不同时,你不能只将s分配给d。这可能更接近您的期望:

{
  d.length = row;

  foreach(i ; 0 .. d.length)
    d[i] = s[i][0..col].dup;
}