Why can't I pass a const array to a function that takes scope const arrays?
Simen Kjærås
simen.kjaras at gmail.com
Mon Feb 17 14:34:44 UTC 2020
On Monday, 17 February 2020 at 14:04:34 UTC, Adnan wrote:
> cdsa ~master: building configuration "cdsa-test-library"...
> source/strassens_matmul.d(22,16): Error: cannot implicitly
> convert expression &mat[row][column] of type const(uint)* to
> uint*
> source/strassens_matmul.d(37,36): Error: template instance
> strassens_matmul.getPointPtr!uint error instantiating
> source/strassens_matmul.d(48,29):
I'd just finished writing a long post explaining the stuff you've
apparently figured out. Ah well. :p
In this case, getPointPtr return T*, but takes scope const ref
T[][]. Since getPointPtr always takes a mutable array, you could
just get rid of const on its parameters. Alternatively, if you
want to be able to use it on arrays of different constness, you
could use inout:
inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t
column) {
This will return a pointer to a mutable T if that's what the
array holds when you call the function, const(T) if it's a const
array, immutable(T) if it's immutable, and so on.
The same can be done with the other functions you have.
You are also somewhat overusing const, scope and ref, I'd say -
you should not take an array by ref unless you plan on modifying
it, which you are not doing in getPointPtr or any other of your
functions. scope may be worth it, as it guarantees you won't be
sending the data elsewhere.
None of these are necessary on your ulongs, which are passed by
value and never attempted modified. If you really like the extra
guarantee that you don't accidentally modify them, feel free to
keep 'const', but 'scope' on a ulong does nothing, and it's been
argued it should be a compiler error.
Lastly, you're using ulongs a lot, and this is mostly correct
when compiling for 64-bit, but makes code fail to compile for
32-bit. Using size_t instead makes for code that works for both.
All in all, I end up with this code:
module strassens_matmul;
debug {
static import std;
}
package {
size_t getRowSize(T)(const T[][] mat) {
return mat[0].length;
}
size_t getColumnSize(T)(const T[][] mat) {
return mat.length;
}
T[][] createMatrix(T)(size_t rowSize, size_t columnSize) {
return new T[][](rowSize, columnSize);
}
/// row and column are 0 index-based
inout(T)* getPointPtr(T)(inout T[][] mat, size_t row, size_t
column) {
return &mat[row][column];
}
T getPointCopy(T)(const T[][] mat, size_t row, size_t column)
{
return mat[row][column];
}
T[][] mulIterative(T)(const T[][] mat1, const T[][] mat2) {
auto result = createMatrix!T(getRowSize!T(mat1),
getColumnSize!T(mat2));
foreach (row; 0 .. mat1.getRowSize()) {
foreach (column; 0 .. mat2.getColumnSize()) {
T value;
foreach (i; 0 .. mat1.getRowSize()) {
value += mat1.getPointCopy(row, i) *
mat2.getPointCopy(i, column);
}
*result.getPointPtr(row, column) = value;
}
}
return result;
}
}
unittest {
const uint[][] matA = [[10, 20, 10], [4, 5, 6], [2, 3, 5]];
const uint[][] matB = [[3, 2, 4], [3, 3, 9], [4, 4, 2]];
const uint[][] matC = [[130, 120, 240], [51, 47, 73], [35,
33, 45]];
assert(matA.mulIterative(matB) == matC);
}
--
Simen
More information about the Digitalmars-d-learn
mailing list