Jump to page: 1 24  
Page
Thread overview
Code fails with linker error. Why?
Oct 03, 2014
eles
Oct 03, 2014
John Colvin
Oct 04, 2014
eles
Oct 04, 2014
eles
Oct 04, 2014
eles
Oct 04, 2014
John Colvin
Oct 04, 2014
eles
Oct 04, 2014
ketmar
Oct 04, 2014
John Colvin
Oct 04, 2014
ketmar
Oct 04, 2014
eles
Oct 04, 2014
John Colvin
Oct 04, 2014
John Colvin
Oct 04, 2014
ketmar
Oct 04, 2014
John Colvin
Oct 04, 2014
ketmar
Oct 04, 2014
John Colvin
Oct 05, 2014
ketmar
Oct 06, 2014
eles
Oct 06, 2014
John Colvin
Oct 06, 2014
eles
Oct 06, 2014
John Colvin
Oct 06, 2014
eles
Oct 06, 2014
John Colvin
Oct 06, 2014
ketmar
Oct 06, 2014
John Colvin
Oct 06, 2014
ketmar
Oct 06, 2014
eles
Oct 06, 2014
John Colvin
Oct 06, 2014
eles
Oct 04, 2014
eles
October 03, 2014
This is under Linux 64 with both dmd 2.066 (and latest gdc-4.9):

=================================================================
class ShapeSurface(T) {
public:
	int formula();
	int getSurfaceBy100() {
		int surface;
		surface = cast(T *)this.formula();
		return surface*100;
	};
};

class Square: ShapeSurface!Square
{
public:
	int squareSize = 8;
	override int formula() {
		return squareSize*squareSize;
	}
};

int main() {

	Square square = new Square();
	square.getSurfaceBy100();

	return 0;
}
=================================================================

It fails with linker error:

dmd app.d
app.o:(.data._D3app31__T12ShapeSurfaceTC3app6SquareZ12ShapeSurface6__vtblZ+0x28): undefined reference to `_D3app31__T12ShapeSurfaceTC3app6SquareZ12ShapeSurface7formulaMFZi'
collect2: error: ld returned 1 exit status
--- errorlevel 1

OK, maybe the cast is broken (well, to a pointer...), so changed this:

		surface = cast(T *)this.formula();
into this:
		T cls = cast(T)this;
		surface = cls.formula();

giving:

dmd app.d
app.o:(.data._D3app31__T12ShapeSurfaceTC3app6SquareZ12ShapeSurface6__vtblZ+0x28): undefined reference to `_D3app31__T12ShapeSurfaceTC3app6SquareZ12ShapeSurface7formulaMFZi'
collect2: error: ld returned 1 exit status
--- errorlevel 1

So, if you could tell me:

1) Why the compiler defer to the linker
2) What is the CRTP equivalent here

Many thanks.
October 03, 2014
On Friday, 3 October 2014 at 15:44:16 UTC, eles wrote:
> class ShapeSurface(T) {
> public:
> 	int formula();

that means you have a definition of formula elsewhere (which the linker tries to find, but obviously fails. What you want is

class ShapeSurface(T) {
public:
	abstract int formula();
October 04, 2014
On Friday, 3 October 2014 at 15:47:33 UTC, John Colvin wrote:
> On Friday, 3 October 2014 at 15:44:16 UTC, eles wrote:
>> class ShapeSurface(T) {
>> public:
>> 	int formula();
>
> that means you have a definition of formula elsewhere (which the linker tries to find, but obviously fails. What you want is
>
> class ShapeSurface(T) {
> public:
> 	abstract int formula();

Thanks, but still. The compiler shall not let that code pass down to the linker. It has everything it needs to not do that, or it shall have. Linker errors shall be simply because the libraries are not in place (either not installed, either linking path not correctly configured, either broken versions of those libraries).

Then, a quirk of D:

this passes and works correctly:

   surface = cast(T *)this.formula();

this segfaults the produced binary:

  surface = (cast(T *)this).formula();

this fails:

   surface = cast(T)this.formula();

with

   app.d(8): Error: cannot cast this.formula() of type int to app.Square

while one has to throw in parentheses to make it work (correctly) once again:

   surface = (cast(T)this).formula();

Isn't this funny, that you have to throw in parentheses depending on the type of the type you cast to?
October 04, 2014
In the original you are casting an int to a pointer type, which is legitimate (although rarely a good idea).  The other side of the matter is simply precedence.

cast(T)a.b;

Is really the same as:

cast(T)(a.b);
October 04, 2014
On Saturday, 4 October 2014 at 09:39:12 UTC, Chris Nicholson-Sauls wrote:
> In the original you are casting an int to a pointer type, which is legitimate (although rarely a good idea).  The other side of the matter is simply precedence.
>
> cast(T)a.b;
>
> Is really the same as:
>
> cast(T)(a.b);

Yes, you are right. Then it's cast back when assigning.
October 04, 2014
On Saturday, 4 October 2014 at 04:02:46 UTC, eles wrote:
> On Friday, 3 October 2014 at 15:47:33 UTC, John Colvin wrote:
>> On Friday, 3 October 2014 at 15:44:16 UTC, eles wrote:
>>> class ShapeSurface(T) {
>>> public:
>>> 	int formula();
>>
>> that means you have a definition of formula elsewhere (which the linker tries to find, but obviously fails. What you want is
>>
>> class ShapeSurface(T) {
>> public:
>> 	abstract int formula();
>
> Thanks, but still. The compiler shall not let that code pass down to the linker. It has everything it needs to not do that, or it shall have. Linker errors shall be simply because the libraries are not in place (either not installed, either linking path not correctly configured, either broken versions of those libraries).

Sorry, but that's just not how it works. There is no requirement for the definition of a function to be found in the same compilation unit as it's declaration.

// a.d
void foo();
void main() { foo(); }

// b.d
import std.stdio;
void foo() { writeln("Hello World"); }

$ ls
a.d     b.d

$ dmd b.d -c

$ ls
a.d     b.d     b.o

$ dmd a.d b.o

$ ls
a       a.d     a.o     b.d     b.o

$ ./a
Hello World


So the compiler has no way of knowing whether you've forgotten to include a definition, or whether it's simply sitting in some other object file / library / whatever. The linker, however, can know, hence the linker error.
October 04, 2014
On Saturday, 4 October 2014 at 09:39:12 UTC, Chris Nicholson-Sauls wrote:
> In the original you are casting an int to a pointer type, which is legitimate (although rarely a good idea).  The other side of the matter is simply precedence.
>
> cast(T)a.b;
>
> Is really the same as:
>
> cast(T)(a.b);

But this also means that the cast is useless there, so there is no compile-time binding, so no CRTP.

Anyway, it ws just a game to write the equivalent.
October 04, 2014
On Saturday, 4 October 2014 at 10:27:18 UTC, John Colvin wrote:
> On Saturday, 4 October 2014 at 04:02:46 UTC, eles wrote:
>> On Friday, 3 October 2014 at 15:47:33 UTC, John Colvin wrote:
>>> On Friday, 3 October 2014 at 15:44:16 UTC, eles wrote:

> So the compiler has no way of knowing whether you've forgotten to include a definition, or whether it's simply sitting in some other object file / library / whatever. The linker, however, can know, hence the linker error.

No "extern" required?...
October 04, 2014
On Sat, 04 Oct 2014 10:27:16 +0000
John Colvin via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
wrote:

> Sorry, but that's just not how it works. There is no requirement for the definition of a function to be found in the same compilation unit as it's declaration.
is there any possibility to declare *class* *method* in one file and to implement it in another? O_O

i doubt so.


October 04, 2014
On Saturday, 4 October 2014 at 10:27:18 UTC, John Colvin wrote:
> On Saturday, 4 October 2014 at 04:02:46 UTC, eles wrote:
>> On Friday, 3 October 2014 at 15:47:33 UTC, John Colvin wrote:
>>> On Friday, 3 October 2014 at 15:44:16 UTC, eles wrote:
>>>> class ShapeSurface(T) {
>>>> public:
>>>> 	int formula();
>>>
>>> that means you have a definition of formula elsewhere (which the linker tries to find, but obviously fails. What you want is
>>>
>>> class ShapeSurface(T) {
>>> public:
>>> 	abstract int formula();
>>
>> Thanks, but still. The compiler shall not let that code pass down to the linker. It has everything it needs to not do that, or it shall have. Linker errors shall be simply because the libraries are not in place (either not installed, either linking path not correctly configured, either broken versions of those libraries).
>
> Sorry, but that's just not how it works. There is no requirement for the definition of a function to be found in the same compilation unit as it's declaration.
>
> // a.d
> void foo();
> void main() { foo(); }
>
> // b.d
> import std.stdio;
> void foo() { writeln("Hello World"); }
>
> $ ls
> a.d     b.d
>
> $ dmd b.d -c
>
> $ ls
> a.d     b.d     b.o
>
> $ dmd a.d b.o
>
> $ ls
> a       a.d     a.o     b.d     b.o
>
> $ ./a
> Hello World

This seem to allow an entire class of problems, by linking against long-time forgotten functions...
« First   ‹ Prev
1 2 3 4