digitalmars.D.learn - Template error on compiling ...
- Robin (56/56) Feb 28 2014 Hiho,
- Tobias Pankrath (7/11) Feb 28 2014 I guess this is the culprit. You must use Matrix!(). In general
- anonymous (3/15) Feb 28 2014 Here it should probably be Matrix!T, though.
- Robin (12/12) Feb 28 2014 Hiho,
- anonymous (10/19) Feb 28 2014 This one gives you the "used as a type" kind of error message.
- Robin (32/32) Feb 28 2014 Hiho,
- anonymous (9/42) Feb 28 2014 The error message is unrelated. "undefined reference to `main'"
- Robin (10/10) Feb 28 2014 Hiho,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (7/9) Feb 28 2014 As I understand it, Matrix is not a type; rather a type template. Only
- Robin (9/9) Feb 28 2014 Hiho,
- Stanislav Blinov (37/45) Feb 28 2014 I'm going to repeat the advice from your thread about matrices:
Hiho, I am currently working on a matrix library (matrices are templated structs) and have just implemented so-called "ElementalOperations" which perform certain tasks on mutable matrices. There is an abstract ElementalOperation where three different ElementalOperation types inherit from. These ElementalOperations are structured like that: module neoLab.core.ScaleRowOperation; import neoLab.core.ElementalOperation; import neoLab.core.Matrix; final class ScaleRowOperation(T = double) : ElementalOperation if (!hasIndirections!T) { private { size_t row = 0; T factor = 1; } this(size_t row, T factor) pure nothrow { this.row = row; this.factor = factor; } override void opCall(ref Matrix m) pure nothrow { foreach (immutable col; 0 .. m.getDimension().cols) { m[this.row, col] *= this.factor; } } override string toString() const pure nothrow { return "Scale all elements of row " ~ this.row ~ " by factor " ~ this.factor ~ "."; } } So it is a fairly simple concept until now and I haven't spend time on improving its performance as I run into a strange compiler error, telling me the following: neoLab/core/ElementalOperation.d(6): Error: struct neoLab.core.Matrix.Matrix(T = double) if (!hasIndirections!T) is used as a type neoLab/core/SwapRowsOperation.d(18): Error: struct neoLab.core.Matrix.Matrix(T = double) if (!hasIndirections!T) is used as a type The matrix struct is defined as follows: struct Matrix(T = double) if (!hasIndirections!T) In the documentation hasIndirections!T reads: Returns true if and only if T's representation includes at least one of the following: - a raw pointer U*; - an array U[]; - a reference to a class type C. - an associative array. - a delegate. I don't know why this error occures at all. In my opinion it shouldn't, or am I doing something wrong again? Thanks in advance for help. =) Robin
Feb 28 2014
On Friday, 28 February 2014 at 19:09:11 UTC, Robin wrote:override void opCall(ref Matrix m) pure nothrow { foreach (immutable col; 0 .. m.getDimension().cols) { m[this.row, col] *= this.factor; }I guess this is the culprit. You must use Matrix!(). In general if the compiler says that "X is used as type", where X is something like a template, than you are using the template X instead of an instance where you should not. There is probably an enhancement request to make the code above legal, though.
Feb 28 2014
On Friday, 28 February 2014 at 19:16:11 UTC, Tobias Pankrath wrote:On Friday, 28 February 2014 at 19:09:11 UTC, Robin wrote:Here it should probably be Matrix!T, though.override void opCall(ref Matrix m) pure nothrow { foreach (immutable col; 0 .. m.getDimension().cols) { m[this.row, col] *= this.factor; }I guess this is the culprit. You must use Matrix!(). In general if the compiler says that "X is used as type", where X is something like a template, than you are using the template X instead of an instance where you should not. There is probably an enhancement request to make the code above legal, though.
Feb 28 2014
Hiho, both opCall(ref Matrix!() m) opCall(ref Matrix!T m) aswell as opCall(ref Matrix!(m)) or just opCall(ref Matrix m) give me all the same error as the one stated in the first post ... :/ Nothing really seems to work here. Robin
Feb 28 2014
On Friday, 28 February 2014 at 19:33:17 UTC, Robin wrote:opCall(ref Matrix!() m) opCall(ref Matrix!T m) aswell as opCall(ref Matrix!(m))This one's just nonsense.or just opCall(ref Matrix m)This one gives you the "used as a type" kind of error message.give me all the same error as the one stated in the first post ... :/You're probably looking in the wrong place (for that particular error message). neoLab/core/ElementalOperation.d, line 6, and neoLab/core/SwapRowsOperation.d, line 18, are the spots the compiler complains about (so far).module neoLab.core.ScaleRowOperation;suggests that you're looking at neither of those two files. You still have to fix it there, too, though.
Feb 28 2014
Hiho, with import neoLab.core.Matrix; abstract class ElementalOperation(T = double) { abstract void opCall(ref Matrix!T m); abstract override string toString(); } where I have made the abstract class templated "(T = double)" and where I have added a "!T" after "Matrix" in the opCall parameter list I get the following error: /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status --- errorlevel 1 When I leave the (T = double) template assignment out I get another error: neoLab/core/ElementalOperation.d(6): Error: undefined identifier T With Tobias Pankrath's Matrix!() I get the following linker error: /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' ScaleRowOperation.o: In function .... many many many lines of unuseful error messages ... (.text._D6neoLab4core6Matrix11__T6MatrixZ6Matrix6randomFxmxmdddZS6neoLab4core6Matrix11__T6Ma rixZ6Matrix+0x145): undefined reference to `_D6neoLab4core9Dimension9Dimension4sizeMxFNaNbNdZm' collect2: error: ld returned 1 exit status --- errorlevel 1 So, in conclusion. I still have no clue why this more or less simple construct does not work but gives me errors on compiling. Robin
Feb 28 2014
On Friday, 28 February 2014 at 20:54:42 UTC, Robin wrote:Hiho, with import neoLab.core.Matrix; abstract class ElementalOperation(T = double) { abstract void opCall(ref Matrix!T m); abstract override string toString(); } where I have made the abstract class templated "(T = double)" and where I have added a "!T" after "Matrix" in the opCall parameter list I get the following error: /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status --- errorlevel 1The error message is unrelated. "undefined reference to `main'" -> no main function. You can add -main to your dmd invocation to let the compiler generate a dummy main.When I leave the (T = double) template assignment out I get another error: neoLab/core/ElementalOperation.d(6): Error: undefined identifier TWell, sure, you just removed T.With Tobias Pankrath's Matrix!() I get the following linker error: /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main'Same as above: no main function.ScaleRowOperation.o: In function .... many many many lines of unuseful error messages ... (.text._D6neoLab4core6Matrix11__T6MatrixZ6Matrix6randomFxmxmdddZS6neoLab4core6Matrix11__T6Ma rixZ6Matrix+0x145): undefined reference to `_D6neoLab4core9Dimension9Dimension4sizeMxFNaNbNdZm' collect2: error: ld returned 1 exit status --- errorlevel 1Can't say much about this. Might just be fallout from previous failures.So, in conclusion. I still have no clue why this more or less simple construct does not work but gives me errors on compiling.Matrix!T is the way to go.
Feb 28 2014
Hiho, aww, that's a noob mistake of me. Thanks! Should take a closer look at the error messages next time a should think more about their special meaning ... It works now while it feels strange that I have to template the three classes as I am only working with references to matrix and in my understanding this shouldn't affect the compilate. But, well, in the end it works now.^^ Robin
Feb 28 2014
On 02/28/2014 02:21 PM, Robin wrote:I am only working with references to matrix and in my understanding this shouldn't affect the compilate.As I understand it, Matrix is not a type; rather a type template. Only instances of that template like Matrix!double can be used as types. I was interested in this thread but I could not put pieces together in my mind without complete code. Could you please demonstrate the problem with minimal code next time. Thanks. :) Ali
Feb 28 2014
Hiho, just for you: the whole code! =) http://dpaste.dzfl.pl/cd1537571a4d The idea is that I have matrix instances and so-called ElementalOperations which are able to operate on matrices to solve certain algorithms object oriented without nasty loops and so on. This had worked perfectly in my java implementation so far. Robin
Feb 28 2014
On Friday, 28 February 2014 at 23:16:48 UTC, Robin wrote:Hiho, just for you: the whole code! =) http://dpaste.dzfl.pl/cd1537571a4d The idea is that I have matrix instances and so-called ElementalOperations which are able to operate on matrices to solve certain algorithms object oriented without nasty loops and so on.I'm going to repeat the advice from your thread about matrices: don't use upper case in module names. See http://dlang.org/module.html#ModuleDeclaration. "delete" keyword will eventually go away, you're better off not using it. Now to a suggestion: how about going up a type so you don't have to carry around the (T = double) and Matrix!T code dependencies? The tests below are simplified and clumped together, but should be enough for an illustration. struct Matrix(T = double) { /* blah */ } /// Tests if type M is a Matrix enum bool isSomeMatrix(M) = is(M == Matrix!T, T); /// Gets element type from a Matrix type alias MatrixElement(M : Matrix!T, T) = T; abstract class ElementalOperation(M) if (isSomeMatrix!M) { /* blah */ } unittest { import std.typetuple; alias types = TypeTuple!(byte,short,int,long,float,double); foreach(T; types) { // don't accept scalars static assert(!isSomeMatrix!T); static assert(!is(MatrixElement!T)); static assert(!is(ElementalOperation!T)); // accept matrices static assert(isSomeMatrix!(Matrix!T)); static assert(is(MatrixElement!(Matrix!T) == T)); static assert(is(ElementalOperation!(Matrix!T))); } } This way all ElementalOperation's method signatures will transform from void foo(Matrix!T m) into void foo(M m), and the MatrixElement template will help in cases when you do need to get to underlying type.This had worked perfectly in my java implementation so far.Well, D is not Java ;) As Ali mentioned, Matrix is not a type, Matrix!T is.
Feb 28 2014
EOn Saturday, 1 March 2014 at 00:17:55 UTC, Stanislav Blinov wrote:/// Tests if type M is a Matrix enum bool isSomeMatrix(M) = is(M == Matrix!T, T);Unrelated, but it may be of some interest. This isn't really a good way to define your isSomeMatrix template, i.e., tying it to a specific type. What if you want to extend your matrix library in the future to include ScalarMatrix, UpperTriangularMatrix, etc. implementations? While these are matrices, they will fail isSomeMatrix as it is defined. A better way when using templates is to define a number of primitives required for an object to be a matrix, and then test for those primitives in isSomeMatrix to determine if M is a matrix. This is the concept of duck-typing, and its how D's ranges are defined. This way, anything that implements the range protocol can be operated on by any range algorithm. It's quite flexible and powerful.
Feb 28 2014
Hiho, thank you for your responses. This D language meta programming sounds funny and strange to someone who has never really worked with something like this but I understand its importance and will look more into working with it. =) Robin
Mar 01 2014