www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Code fails with linker error. Why?

reply "eles" <eles eles.com> writes:
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__T12ShapeSurfaceTC3app6SquareZ12ShapeSu
face6__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__T12ShapeSurfaceTC3app6SquareZ12ShapeSu
face6__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.
Oct 03 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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();
Oct 03 2014
parent reply "eles" <eles215 gzk.dot> writes:
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?
Oct 03 2014
next sibling parent reply "Chris Nicholson-Sauls" <ibisbasenji gmail.com> writes:
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);
Oct 04 2014
next sibling parent "eles" <eles215 gzk.dot> writes:
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.
Oct 04 2014
prev sibling parent "eles" <eles215 gzk.dot> writes:
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.
Oct 04 2014
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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.
Oct 04 2014
next sibling parent reply "eles" <eles215 gzk.dot> writes:
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?...
Oct 04 2014
next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 04 Oct 2014 10:37:39 +0000
eles via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 No "extern" required?...
nope.
Oct 04 2014
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 4 October 2014 at 10:37:40 UTC, eles wrote:
 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?...
nope, no extern required. The extern you are referring to is the storage class http://dlang.org/declaration.html#extern and is for variables.
 This seem to allow an entire class of problems, by linking 
 against long-time forgotten functions...
It's the core functionality that allows you to link to a function in a library without having the entire source available. You have a declaration, but the implementation is in another object file / library. D is slightly tighter than C wrt all this. In C, you can just call functions without even having a declaration, the compiler will assume the argument types from what you passed in. A forgotten #include and compiling without warnings = horrific bugs in C. In D the declaration is required.
Oct 04 2014
prev sibling next sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
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=20
 for the definition of a function to be found in the same=20
 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.
Oct 04 2014
next sibling parent "eles" <eles215 gzk.dot> writes:
On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 10:27:16 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:
 is there any possibility to declare *class* *method* in one
Yes, that too. Is even worse.
Oct 04 2014
prev sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
Digitalmars-d-learn wrote:
 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.
Yes, you can. You just have to get the mangling right. // methodLink.d class A { void foo(); } void main() { auto a = new A; a.foo(); } // missingMethod.d import methodLink; import std.stdio; pragma(mangle, A.foo.mangleof) void foo() { writeln("Hello World"); } $ dmd missingMethod.d -c $ dmd methodLink.d missingMethod.o $ ./methodLink Hello World
Oct 04 2014
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 4 October 2014 at 11:01:30 UTC, John Colvin wrote:
 On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 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.
Yes, you can. You just have to get the mangling right. // methodLink.d class A { void foo(); } void main() { auto a = new A; a.foo(); } // missingMethod.d import methodLink; import std.stdio; pragma(mangle, A.foo.mangleof) void foo() { writeln("Hello World"); } $ dmd missingMethod.d -c $ dmd methodLink.d missingMethod.o $ ./methodLink Hello World
Inheritance works too: //methodLink.d import std.stdio; class Base { void foo() { writeln("From Base"); } } class A : Base { override void foo(); } void main() { Base a = new A; a.foo(); a.Base.foo(); } $ dmd methodLink.d missingMethod.o $ ./methodLink Hello World From Base
Oct 04 2014
prev sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 04 Oct 2014 11:01:28 +0000
John Colvin via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via=20
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 10:27:16 +0000
 John Colvin via Digitalmars-d-learn=20
 <digitalmars-d-learn puremagic.com>
 wrote:

 Sorry, but that's just not how it works. There is no=20
 requirement for the definition of a function to be found in=20
 the same compilation unit as it's declaration.
is there any possibility to declare *class* *method* in one=20 file and to implement it in another? O_O i doubt so.
=20 Yes, you can. You just have to get the mangling right.
and how about access to class fields? manual mangling is a half-working hack. alas. i really want to have some normal and non-hackish way to separate class definition and class implementation. besides, your trick is faulty, 'cause it misses hidden 'this' parameter. try that: // methodLink.d class A { void foo(int n); } void main () { auto a =3D new A; a.foo(42); } // missingMethod.d import methodLink; import std.stdio; pragma(mangle, A.foo.mangleof) void foo(int n) { writeln("n=3D", n); } it writes gibberish and segfaults.
Oct 04 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 4 October 2014 at 11:19:52 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 11:01:28 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 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.
Yes, you can. You just have to get the mangling right.
and how about access to class fields? manual mangling is a half-working hack. alas. i really want to have some normal and non-hackish way to separate class definition and class implementation. besides, your trick is faulty, 'cause it misses hidden 'this' parameter. try that: // methodLink.d class A { void foo(int n); } void main () { auto a = new A; a.foo(42); } // missingMethod.d import methodLink; import std.stdio; pragma(mangle, A.foo.mangleof) void foo(int n) { writeln("n=", n); } it writes gibberish and segfaults.
good catch. This works for me, but it's probably not portable due to variations in where the hidden this is passed: //methodLink import std.stdio; class Base { int baseVal; void foo(int a) { writeln("baseVal + a: ", baseVal + a); } } class A : Base { int aVal; this(int v) { aVal = v; baseVal = 2*v; } override void foo(int a); } void main() { Base a = new A(42); a.foo(3); a.Base.foo(3); } // missingMethod.d import methodLink; import std.stdio; pragma(mangle, A.foo.mangleof) void foo(int a, A this_) { writeln("aVal + a: ", this_.aVal + a); } $./methodLink aVal + a: 45 baseVal + a: 87 I don't really see the point though. class A { void foo(int a) { Afoo(this, a); } } then declare and define Afoo however you like.
Oct 04 2014
next sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 04 Oct 2014 15:29:55 +0000
John Colvin via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 I don't really see the point though.
=20
 class A
 {
      void foo(int a) { Afoo(this, a); }
 }
=20
 then declare and define Afoo however you like.
it's noisy hackery and namespace pollution. sure i can do this and i'm using this trick when it's better to define some methods for class/struct in another module, but i don't like it. inheritance/interfaces is not the best solution sometimes. sure, i can `import()` any text file, but this is not good for separate compilation (and this is why i want this feature in the first place). to make a long story short: i don't like such hacks. ;-) but i'm not yet familiar with compiler internals enough to write a patch.
Oct 04 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Saturday, 4 October 2014 at 15:54:26 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 15:29:55 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 I don't really see the point though.
 
 class A
 {
      void foo(int a) { Afoo(this, a); }
 }
 
 then declare and define Afoo however you like.
it's noisy hackery and namespace pollution. sure i can do this and i'm using this trick when it's better to define some methods for class/struct in another module, but i don't like it.
It is a little noisy, but really very little. The only extra noise is the call to Afoo. Namespace pollution? In what way would that cause a problem here?
Oct 04 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 04 Oct 2014 16:52:08 +0000
John Colvin via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 It is a little noisy, but really very little. The only extra=20
 noise is the call to Afoo.
it's "very little" turns to "alot" with alot of classes with alot of methods. and code readability suffers even from one such hack.
 Namespace pollution? In what way would that cause a problem here?
all this AFoo, BFoo, CFoo, XYZFoo are useless. all they do is polluting namespace, making debug info bigger and processing debug info slower. each unnecessary thing that computer must process is... well, unnecessary. ;-) i'm doing some tricks with debug info -- such as live code instrumentation, and i hate all that 'proxies'. ;-) i again must write code to deal with things that compiler should deal with.
Oct 04 2014
prev sibling parent reply "eles" <eles eles.com> writes:
On Saturday, 4 October 2014 at 15:29:57 UTC, John Colvin wrote:
 On Saturday, 4 October 2014 at 11:19:52 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 11:01:28 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 10:27:16 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:
 I don't really see the point though.

 class A
 {
     void foo(int a) { Afoo(this, a); }
 }

 then declare and define Afoo however you like.
That's hackish, bad and convoluted. And it does not/should not allow one to mess with the private fields of the class, especially if Afoo is defined in another module. And on that matter, a function that is to be provided by another module should be explicitly marked as such in its declaration. Otherwise, I could declare a function, forget to provide its definition, still having the surprise that the code compiles and runs with very strange results because some other module provides a function that just happens to work. Let's not even say how messy this could get with version() where you could disable a function definition by error, in one version, but still have a software that compiles and runs nowhere.
Oct 06 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 6 October 2014 at 10:10:04 UTC, eles wrote:
 On Saturday, 4 October 2014 at 15:29:57 UTC, John Colvin wrote:
 On Saturday, 4 October 2014 at 11:19:52 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 11:01:28 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 10:27:16 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:
 I don't really see the point though.

 class A
 {
    void foo(int a) { Afoo(this, a); }
 }

 then declare and define Afoo however you like.
That's hackish, bad and convoluted.
I disagree. It's simple and easy to understand.
 And it does not/should not allow one to mess with the private 
 fields of the class, especially if Afoo is defined in another 
 module.
s/especially/only This is the only genuine problem I can see that requires a language extension. Separating class definition from method definition in to different compilation units doesn't allow access to private members without very nasty hacks.
 And on that matter, a function that is to be provided by 
 another module should be explicitly marked as such in its 
 declaration.

 Otherwise, I could declare a function, forget to provide its 
 definition, still having the surprise that the code compiles 
 and runs with very strange results because some other module 
 provides a function that just happens to work.
I don't quite follow. Example?
 Let's not even say how messy this could get with version() 
 where you could disable a function definition by error, in one 
 version, but still have a software that compiles and runs 
 nowhere.
Oct 06 2014
next sibling parent reply "eles" <eles eles.com> writes:
On Monday, 6 October 2014 at 11:54:56 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 10:10:04 UTC, eles wrote:
 On Saturday, 4 October 2014 at 15:29:57 UTC, John Colvin wrote:
 On Saturday, 4 October 2014 at 11:19:52 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 11:01:28 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 10:27:16 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:
 I don't quite follow. Example?
Well, in the OP example, imagine that I was trying to compile this module along with another one that simply happened to have a method defined in a way that the linker would have find it. I would have compiled with: dmd app.d app2.d and be unaware what bug I have introduced because I forgot do declare formula() as abstract in the first class.
Oct 06 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 6 October 2014 at 12:16:14 UTC, eles wrote:
 On Monday, 6 October 2014 at 11:54:56 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 10:10:04 UTC, eles wrote:
 On Saturday, 4 October 2014 at 15:29:57 UTC, John Colvin 
 wrote:
 On Saturday, 4 October 2014 at 11:19:52 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 11:01:28 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 On Saturday, 4 October 2014 at 10:38:32 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 10:27:16 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:
 I don't quite follow. Example?
Well, in the OP example, imagine that I was trying to compile this module along with another one that simply happened to have a method defined in a way that the linker would have find it. I would have compiled with: dmd app.d app2.d and be unaware what bug I have introduced because I forgot do declare formula() as abstract in the first class.
This isn't a problem. You're not going to get the name-mangling right by accident. Even for free functions the module name is mangled in. The only way this can happen is with extern(C) functions, which is because C doesn't mangle it's function names.
Oct 06 2014
parent reply "eles" <eles eles.com> writes:
On Monday, 6 October 2014 at 13:23:55 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 12:16:14 UTC, eles wrote:
 On Monday, 6 October 2014 at 11:54:56 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 10:10:04 UTC, eles wrote:
 On Saturday, 4 October 2014 at 15:29:57 UTC, John Colvin 
 wrote:
 On Saturday, 4 October 2014 at 11:19:52 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 11:01:28 +0000
 John Colvin via Digitalmars-d-learn
 This isn't a problem. You're not going to get the name-mangling 
 right by accident. Even for free functions the module name is 
 mangled in.
It is. I could erase the definition of an identical class in another .d file and accidentally leave an orphan definition method therein.
 The only way this can happen is with extern(C) functions, which 
 is because C doesn't mangle it's function names.
This too is a hole. Why to leave holes? I like the "fromage à trous": http://fr.wikipedia.org/wiki/Paradoxe_du_fromage_à_trous But not in my software.
Oct 06 2014
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 6 October 2014 at 16:02:40 UTC, eles wrote:
 On Monday, 6 October 2014 at 13:23:55 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 12:16:14 UTC, eles wrote:
 On Monday, 6 October 2014 at 11:54:56 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 10:10:04 UTC, eles wrote:
 On Saturday, 4 October 2014 at 15:29:57 UTC, John Colvin 
 wrote:
 On Saturday, 4 October 2014 at 11:19:52 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Sat, 04 Oct 2014 11:01:28 +0000
 John Colvin via Digitalmars-d-learn
 This isn't a problem. You're not going to get the 
 name-mangling right by accident. Even for free functions the 
 module name is mangled in.
It is. I could erase the definition of an identical class in another .d file and accidentally leave an orphan definition method therein.
Unless I misunderstand you, this can't happen. Class methods are mangled to contain the module name and the class name. I can't think of a way of getting the same mangling and getting a bad substitution without either a) pragma(mangle, ...) or b) you have 2 modules with the same name, containing classes with the same name, which you compile completely separately (to prevent the compiler complaining about the duplication), then link the results together. This would also work for free functions. a) is a deliberate feature. b) has bypassed the compiler completely, there's no way it can know. You're never going to do it by accident.
 The only way this can happen is with extern(C) functions, 
 which is because C doesn't mangle it's function names.
This too is a hole. Why to leave holes?
Because it's how C linkage works and if we're using extern(C), it means we want C linkage. That's the point of extern(C).
Oct 06 2014
prev sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Mon, 06 Oct 2014 11:54:55 +0000
John Colvin via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 I disagree. It's simple and easy to understand.
and hackish.
 This is the only genuine problem I can see that requires a=20
 language extension. Separating class definition from method=20
 definition in to different compilation units doesn't allow access=20
 to private members without very nasty hacks.
no hacks needed. =3D=3D pkg.classdef.d =3D=3D module pkg.classdef; class A { private: int hiddenField; int bar (); } =3D=3D pkg.othermodule.d =3D=3D=3D module pkg.othermodule; import pkg.classdef; // this imlements A.bar() declared in pkg.classdef: implementation(A) int bar () { return this.hiddenField; } compiler is perfectly able to put A.bar() implementation in the scope of A, and then A.bar can access anything in A. it's the same as declaring bar() in class definition.
Oct 06 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 6 October 2014 at 12:36:41 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Mon, 06 Oct 2014 11:54:55 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 I disagree. It's simple and easy to understand.
and hackish.
D is very amenable to slightly hackish code.
 This is the only genuine problem I can see that requires a 
 language extension. Separating class definition from method 
 definition in to different compilation units doesn't allow 
 access to private members without very nasty hacks.
 no hacks needed.
I meant that without a language change, one does need hacks.
 == pkg.classdef.d ==
   module pkg.classdef;
   class A {
   private:
     int hiddenField;
     int bar ();
   }


 == pkg.othermodule.d ===
   module pkg.othermodule;
   import pkg.classdef;
   // this imlements A.bar() declared in pkg.classdef:
    implementation(A) int bar () { return this.hiddenField; }

 compiler is perfectly able to put A.bar() implementation in the 
 scope
 of A, and then A.bar can access anything in A. it's the same as
 declaring bar() in class definition.
That would be nice, although personally I'd prefer int A.bar() { return this.hiddenField; } as it's less verbose and would be familiar to c++ programmers.
Oct 06 2014
next sibling parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Mon, 06 Oct 2014 15:44:34 +0000
John Colvin via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

 I disagree. It's simple and easy to understand.
and hackish.
D is very amenable to slightly hackish code.
D allows to write hackish code, and it's good. but if we can provide a way to write less hackish code, it's good and preferable, i think. ;-)
 no hacks needed.
I meant that without a language change, one does need hacks.
i see.
 That would be nice, although personally I'd prefer
=20
 int A.bar() { return this.hiddenField; }
=20
 as it's less verbose and would be familiar to c++ programmers.
i was trying to not change grammar, that's why i invented that horribly-looking implementation attribute. this way the code is still marked as a hack, but "officially endorsed" hack. besides, attribute allows to use code blocks: implementation(A) { int foo () { ... } void bar () { ... } } or even: implementation(A): int foo () { ... } void bar () { ... } sure, it has it's own pack of problems: implementation(A) { implementation(B) { // I'M LOST! } } but we can have both! ;-)
Oct 06 2014
prev sibling parent reply "eles" <eles eles.com> writes:
On Monday, 6 October 2014 at 15:44:36 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 12:36:41 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Mon, 06 Oct 2014 11:54:55 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 I disagree. It's simple and easy to understand.
and hackish.
D is very amenable to slightly hackish code.
 This is the only genuine problem I can see that requires a 
 language extension. Separating class definition from method 
 definition in to different compilation units doesn't allow 
 access to private members without very nasty hacks.
 no hacks needed.
I meant that without a language change, one does need hacks.
So, you admit it is a hack! Gotcha!
Oct 06 2014
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 6 October 2014 at 16:04:02 UTC, eles wrote:
 On Monday, 6 October 2014 at 15:44:36 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 12:36:41 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Mon, 06 Oct 2014 11:54:55 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 wrote:

 I disagree. It's simple and easy to understand.
and hackish.
D is very amenable to slightly hackish code.
 This is the only genuine problem I can see that requires a 
 language extension. Separating class definition from method 
 definition in to different compilation units doesn't allow 
 access to private members without very nasty hacks.
 no hacks needed.
I meant that without a language change, one does need hacks.
So, you admit it is a hack! Gotcha!
In order to get access to private variables from another compilation unit, yes, you need some nasty hackiness. I haven't presented such a hack though.
Oct 06 2014
parent "eles" <eles215 gzk.dot> writes:
On Monday, 6 October 2014 at 19:03:13 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 16:04:02 UTC, eles wrote:
 On Monday, 6 October 2014 at 15:44:36 UTC, John Colvin wrote:
 On Monday, 6 October 2014 at 12:36:41 UTC, ketmar via 
 Digitalmars-d-learn wrote:
 On Mon, 06 Oct 2014 11:54:55 +0000
 John Colvin via Digitalmars-d-learn 
 <digitalmars-d-learn puremagic.com>
 In order to get access to private variables from another 
 compilation unit, yes, you need some nasty hackiness. I haven't 
 presented such a hack though.
I know. Was not serious.
Oct 06 2014
prev sibling parent "eles" <eles215 gzk.dot> writes:
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...
Oct 04 2014