2012-01-15 8 views
10

Esto funciona:es una matriz estática un rango de avance?

int[] a = [ 1, 2, 3, 4 ]; 
fill(a, 5); 

pero esto no es así:

int[4] a = [ 1, 2, 3, 4 ]; 
fill(a, 5); 

y me da este error:

Error: template std.algorithm.fill(Range,Value) if (isForwardRange!(Range) && is(typeof(range.front = filler))) does not match any function template declaration

lugar, tengo que hacer esto con el fin de que se trabajar con matrices estáticas:

int[4] a = [ 1, 2, 3, 4 ]; 
fill(a[], 5); 

podría alguien explicar este comportamiento, por favor?

Respuesta

7

No. isForwardRange es false para matrices estáticas, ya que no son intervalos de avance válidos. Deben tener un válido front, empty y popFront.

Un rango debe ser mutado a medida que se itera. popFront elimina el primer elemento del rango, reduciendo la longitud del rango en uno. arrays estáticos no pueden ser mutados. Sus elementos pueden ser, pero no pueden ser.

int[5] a; 
a.length = 4; 

es ilegal. Por lo tanto, popFront no puede trabajar con matrices estáticas y, por lo tanto, las matrices estáticas no pueden ser intervalos.

front, empty, y popFront se declaran para matrices en std.array, y front y empty trabajará con matrices estáticas, ya que explícitamente toman matrices dinámicas (no rangos), y matrices estáticas se puede convertir implícitamente a matrices dinámicas cuando una función toma una matriz dinámica (se toma una porción de la matriz estática). Sin embargo, popFront no funcionará, ya que requiere un ref de una matriz dinámica. Y como, señalé, popFront no se puede hacer para trabajar con matrices estáticas independientemente de la implementación de popFront, porque no se puede mutar una matriz estática como sería necesario para un rango.

Ahora, como para fill, toma un rango de avance, no una matriz. Entonces, IFTI (instanciación de plantilla de función implícita) intentará y usará el tipo de matriz estática (no el tipo de matriz dinámica) con ella. Y dado que isForwardRange es false para una matriz estática, fill no se puede compilar con una matriz estática. Sin embargo, cuando segmenta la matriz estática, está pasando una matriz dinámica, para la cual isForwardRangeestrue. Entonces, funcionaY debido a que el corte señala a los mismos elementos y fill muta los elementos y no la matriz, los elementos en la matriz estática están mutados por fill.

Tenga cuidado, sin embargo, de pasar porciones de arreglos estáticos a las funciones. Mientras exista la matriz estática, está bien. Pero una vez que la matriz estática deja alcance, cualquier porción de la misma no es válida. Por lo tanto, haciendo algo como

int[] foo() 
{ 
    int[5] a = [1, 2, 3, 4, 5] 
    return find(a[], 3); 
} 

sería muy malo. Una referencia a a está escapando foo, es decir, una porción de sus últimos 3 elementos.

Por lo tanto, si está pasando una porción de una matriz estática a una función, debe asegurarse de que no haya referencias a esa matriz. fill, sin embargo, debería estar bien.

+0

¿Tengo razón al decir que también debes cortar con 'Array' y' SList'? Parece un poco un defecto de diseño. –

+0

No es realmente un defecto de diseño en mi humilde opinión. Es más un caso que las matrices dinámicas son un extraño caso especial de rangos. Pero dado que actualmente son el caso más común, es a lo que estamos acostumbrados. Un contenedor debería convertir implícitamente a su tipo de sector para IFTI para que no tenga que cortarse explícitamente al pasar a una función, y eso haría mucho más difícil pasar contenedores a funciones con plantilla. Y no estoy seguro de que sea una buena idea que todos los tipos rebanables se corten automáticamente con IFTI en general, incluso cuando se trata solo de rangos. –

+0

Puedes pensarlo así. Los contenedores, incluidas las matrices estáticas, deben dividirse para obtener un rango sobre ellos. Por lo tanto, si desea un rango sobre ellos por cualquier motivo, incluido el paso a una función basada en el rango, debe dividirlos explícitamente. Pero los arreglos dinámicos ya tienen rangos en lugar de contenedores, por lo que no es necesario cortarlos. –

7

isForwardRange comprueba la existencia de la front, empty propiedades y popfront() función

el problema es que popfront() tendría que reducir el tamaño del array, ya que (debe) sabe que puede no cambiar el tamaño de una matriz estática, sino una rebanada de una matriz estática (esencialmente una matriz dinámica normal) puede cambiar el tamaño (esto por supuesto no afecta a la matriz estática)

aclarar a.popfront() necesitaría para transformar una de int[4] a int[3] pero eso no es posible

+0

i.e. ¿Los tipos de argumento y retorno de popfront deben ser los mismos? – BCS

+0

'popfront' es una función que cambia el parámetro' this' para que la propiedad 'front' cambie (apuntando al 'próximo' elemento) (y tal vez la propiedad' empty') esto no es posible con la matriz estática porque el la longitud se establece en tiempo de compilación y parte del tipo. –

Cuestiones relacionadas