www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - extern(C++) and struct (constness mangling problem ?)

reply deadalnix <deadalnix gmail.com> writes:
Hi,

I did face a problem with extern(C++) again. Now we are talkign about 
const member method for structs. Here is a sample code to trigger the 
error :

extern(C++) {
	struct Fail {
		void method() {}
		void method() const {}
	}
}

It will generate the error Error: symbol `_ZN4Fail6methodEv' is already 
defined.

Both method are mangled the same way, regardless of constness.

On a more general basis, interfacing to C++ is damn hard to do safely ! 
If you put asside some mangling bugs, some D choices make it more 
difficult than necessary.

Notably, it's very difficult to map a C++ POD class with a default 
constructor and copy constructor/assignement overload. struct doesn't 
allow for default constructor and copy constructor isn't mappable using 
posblit. final class imply an overhead, and are references types (so 
cannot be passed by value).
Nov 29 2011
next sibling parent reply "Martin Nowak" <dawg dawgfoto.de> writes:
On Tue, 29 Nov 2011 16:46:55 +0100, deadalnix <deadalnix gmail.com> wrote:

 Hi,

 I did face a problem with extern(C++) again. Now we are talkign about  
 const member method for structs. Here is a sample code to trigger the  
 error :

 extern(C++) {
 	struct Fail {
 		void method() {}
 		void method() const {}
 	}
 }

 It will generate the error Error: symbol `_ZN4Fail6methodEv' is already  
 defined.

 Both method are mangled the same way, regardless of constness.

 On a more general basis, interfacing to C++ is damn hard to do safely !  
 If you put asside some mangling bugs, some D choices make it more  
 difficult than necessary.

 Notably, it's very difficult to map a C++ POD class with a default  
 constructor and copy constructor/assignement overload. struct doesn't

And yes it is not possible to map all C++ concepts to D.
 allow for default constructor and copy constructor isn't mappable using  
 posblit. final class imply an overhead, and are references types (so  
 cannot be passed by value).

inexistent (I'm not aware of any language that achieves this). I've recently posted a feasible solution to allocate C++ classes using the D garbage collector and profit from automatic lifetime management. https://gist.github.com/1391734 Given that all bugs get sorted out, one can expect three mechanisms to work. - Calling free C++ functions and probably non-virtual methods - Pass POD data forth and back - Call virtual methods of classes with known vtable layout Some more things as calling namespace function or certain templates could probably be provided by a library. But it should suffice to provide zero overhead interfacing to most C++ code. Interfacing QT with it's heavy use of virtual calls, multiple-inheritance and a custom pre-processor will require an additional simplifying wrapper layer on the C++ side. martin
Nov 29 2011
parent reply deadalnix <deadalnix gmail.com> writes:
Le 29/11/2011 18:08, Martin Nowak a écrit :
 On Tue, 29 Nov 2011 16:46:55 +0100, deadalnix <deadalnix gmail.com> wrote:
 Notably, it's very difficult to map a C++ POD class with a default
 constructor and copy constructor/assignement overload. struct doesn't

And yes it is not possible to map all C++ concepts to D.

OK, usage of POD was not the right term. But as matter of fact, C++ gives you 2 general direction to use structs/classes : 1/ You make your struct/class non copyable (making copy constructor and assignement operator private for exemple), the destructor virtual and use it as a polymorphic type. This is what D's class is supposed to do. 2/ Use that stract/class as a value type. You can do POD, but also define constructor and destructor, copy constructor and overload assignement. Anyway, you'll never be able to use proper polymorphism here, because it would require virtual destructor at least. This is IMO, what D's struct should achieve. The 2/ case is overly used in almost any C++ program. And D struct should be able to match them. It wouldn't require much to make it working : - Default constructor. - The hability to define opAssign for it's own type if this(this) is disabled. Today we have 2 options in D : go for struct and get an error prone binding (it's very easy to get a garbage struct, because you cannot enforce that you'll go throw the constructor, and you cannot map copy constructor, even with additionnal C++ code). Or you can go final class, but you don't have a value type anymore and it become quite hard to pass the object to/from C++, because of the header of the object. If you get one from C++, you need the rewrap it in a object on the D side, but . . . the copy constructor isn't mappable. So you need to play ping pong between D and C++ to allocated the D object, then go back to C++ to copy the data using the proper copy code, and then go back to D to do something with that. Plus you need an heap allocation (which isn't inexpansive ATM, because of the lock in it, and cannot compete with stack anyway).
 allow for default constructor and copy constructor isn't mappable
 using posblit. final class imply an overhead, and are references types
 (so cannot be passed by value).

inexistent (I'm not aware of any language that achieves this). I've recently posted a feasible solution to allocate C++ classes using the D garbage collector and profit from automatic lifetime management. https://gist.github.com/1391734 Given that all bugs get sorted out, one can expect three mechanisms to work. - Calling free C++ functions and probably non-virtual methods - Pass POD data forth and back - Call virtual methods of classes with known vtable layout Some more things as calling namespace function or certain templates could probably be provided by a library. But it should suffice to provide zero overhead interfacing to most C++ code. Interfacing QT with it's heavy use of virtual calls, multiple-inheritance and a custom pre-processor will require an additional simplifying wrapper layer on the C++ side. martin

I did had a look at that code just befor you posted (somebody mention that on irc). This is a nice piece of code. But clearly solve another problem that the one I'm talking about. If your are interested I wrote something about starting thread on the C++ side but remaining compatible with D (so you can call D code from the C++ thread) here : http://www.deadalnix.42/2011/11/24/interfacing-d-with-c-start-new-thread/ (require 42registry).
Nov 29 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it working :
 - Default constructor.

No.
 - The hability to define opAssign for it's own type if this(this) is
 disabled.

Yes. That's a bug. Could you please file? Thanks, Andrei
Nov 29 2011
parent reply deadalnix <deadalnix gmail.com> writes:
Le 29/11/2011 19:52, Andrei Alexandrescu a écrit :
 On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it
 working :
 - Default constructor.

No.

No, as "No it will never be done for reason xxx" or as in "No you are wrong and it not necessary, here the way to do : xxx". In both cases, the xxx is the most interesting part :'(
 - The hability to define opAssign for it's own type if this(this) is
 disabled.

Yes. That's a bug. Could you please file?

Doing it right now. Have to get a sample code and actual compiler output. That would solve at least the copy problem.
Nov 29 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/29/11 11:39 AM, deadalnix wrote:
 Le 29/11/2011 19:52, Andrei Alexandrescu a écrit :
 On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it
 working :
 - Default constructor.

No.

No, as "No it will never be done for reason xxx" or as in "No you are wrong and it not necessary, here the way to do : xxx". In both cases, the xxx is the most interesting part :'(

Neither :o). The default initializer that doesn't do any real "work", does not throw, and puts the object in a state without ex-situ ownership has brought D too many benefits to ignore. We should be able to define types that refuse default initialization (a la non-null pointers), but if the default initializer exists, it's good as it is. Andrei
Nov 29 2011
next sibling parent reply deadalnix <deadalnix gmail.com> writes:
Le 29/11/2011 22:09, Andrei Alexandrescu a écrit :
 On 11/29/11 11:39 AM, deadalnix wrote:
 Le 29/11/2011 19:52, Andrei Alexandrescu a écrit :
 On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is
 IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it
 working :
 - Default constructor.

No.

No, as "No it will never be done for reason xxx" or as in "No you are wrong and it not necessary, here the way to do : xxx". In both cases, the xxx is the most interesting part :'(

Neither :o). The default initializer that doesn't do any real "work", does not throw, and puts the object in a state without ex-situ ownership has brought D too many benefits to ignore. We should be able to define types that refuse default initialization (a la non-null pointers), but if the default initializer exists, it's good as it is. Andrei

I do not question the benefit of initializer that don't do any real "work" as you said. This is definitively a good thing. What I question, is the impossibility for the programmer to do another way. This result in very convoluted way to interract with C++. The D phylosophy is to enforce a clean and safe way to do thing (and default initializer definitively goes in that direction) but also open the possibility to get dirty and do whatever is required to do yout hanky panky stuffs. Here is what I suggest : - struct with no default constructor just behave the same way as the did until now. - struct can disable the default constructor as it is possible now. If you create a variable of that type without initialization, you get an error. - struct can define a default constructor. You get the same errors as you get when you disable that default constructor. With some code : struct S { // default constructor defined or disabled } S s; // Error if the default constructor is defined or disabled; S s = S(); // OK if you have a default constructor, error otherwize. S s = S.init; // Call the postblit if a default constructor exists or is disabled That way, we keep the benefit of default initializer for most struct, but open the door for programmers that don't know what fear is about. This modify the behaviour of the struct, but, ATM, the default constructor can be disabled, and it result in inconsistent behaviour (exemple 1 generate error, exemple 3 compile fine and don't call postblit). As the behaviour is different - we losse benefits of default initializers -, we may want to explicit that with a keyword. As you suggested, this is similar with non nullable references and could use the same keyword (and this is a feature that is missing definitively, null check is so easy to forget that it would be great that the compiler help us in the task). This definitively have an impact on severals aspect of D (resising arrays is a good exemple). Thoses would be impacted by the default constructor caracteritics (eventually can throw, become exepensive in computation, etc . . .). We may want to disable thoses operations on such types or limit them in some ways. By the way, bug on opAssign is filled now.
Nov 29 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 11/29/2011 10:46 PM, deadalnix wrote:
 Le 29/11/2011 22:09, Andrei Alexandrescu a écrit :
 On 11/29/11 11:39 AM, deadalnix wrote:
 Le 29/11/2011 19:52, Andrei Alexandrescu a écrit :
 On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is
 IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it
 working :
 - Default constructor.

No.

No, as "No it will never be done for reason xxx" or as in "No you are wrong and it not necessary, here the way to do : xxx". In both cases, the xxx is the most interesting part :'(

Neither :o). The default initializer that doesn't do any real "work", does not throw, and puts the object in a state without ex-situ ownership has brought D too many benefits to ignore. We should be able to define types that refuse default initialization (a la non-null pointers), but if the default initializer exists, it's good as it is. Andrei

I do not question the benefit of initializer that don't do any real "work" as you said. This is definitively a good thing. What I question, is the impossibility for the programmer to do another way. This result in very convoluted way to interract with C++. The D phylosophy is to enforce a clean and safe way to do thing (and default initializer definitively goes in that direction) but also open the possibility to get dirty and do whatever is required to do yout hanky panky stuffs. Here is what I suggest : - struct with no default constructor just behave the same way as the did until now. - struct can disable the default constructor as it is possible now. If you create a variable of that type without initialization, you get an error. - struct can define a default constructor. You get the same errors as you get when you disable that default constructor. With some code : struct S { // default constructor defined or disabled } S s; // Error if the default constructor is defined or disabled; S s = S(); // OK if you have a default constructor, error otherwize. S s = S.init; // Call the postblit if a default constructor exists or is disabled That way, we keep the benefit of default initializer for most struct, but open the door for programmers that don't know what fear is about. This modify the behaviour of the struct, but, ATM, the default constructor can be disabled, and it result in inconsistent behaviour (exemple 1 generate error, exemple 3 compile fine and don't call postblit). As the behaviour is different - we losse benefits of default initializers -, we may want to explicit that with a keyword. As you suggested, this is similar with non nullable references and could use the same keyword (and this is a feature that is missing definitively, null check is so easy to forget that it would be great that the compiler help us in the task). This definitively have an impact on severals aspect of D (resising arrays is a good exemple). Thoses would be impacted by the default constructor caracteritics (eventually can throw, become exepensive in computation, etc . . .). We may want to disable thoses operations on such types or limit them in some ways. By the way, bug on opAssign is filled now.

I think it is a reasonable request to allow S s = S(), because you can get the same with static opCall already (more inconvenient though, and no way to get it to work with extern(C++) structs). But I am not sure what to do about the S s = S.init; situation. Calling the postblit is just wrong, because there is no copying going on: S.init is constructed and then _moved_ into s. Move semantics are important, because it allows D code to translate to much faster code than C++98 code that always has to copy and destroy instead of moving.
Nov 29 2011
parent deadalnix <deadalnix gmail.com> writes:
Le 29/11/2011 23:06, Timon Gehr a écrit :
 On 11/29/2011 10:46 PM, deadalnix wrote:
 Le 29/11/2011 22:09, Andrei Alexandrescu a écrit :
 On 11/29/11 11:39 AM, deadalnix wrote:
 Le 29/11/2011 19:52, Andrei Alexandrescu a écrit :
 On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is
 IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it
 working :
 - Default constructor.

No.

No, as "No it will never be done for reason xxx" or as in "No you are wrong and it not necessary, here the way to do : xxx". In both cases, the xxx is the most interesting part :'(

Neither :o). The default initializer that doesn't do any real "work", does not throw, and puts the object in a state without ex-situ ownership has brought D too many benefits to ignore. We should be able to define types that refuse default initialization (a la non-null pointers), but if the default initializer exists, it's good as it is. Andrei

I do not question the benefit of initializer that don't do any real "work" as you said. This is definitively a good thing. What I question, is the impossibility for the programmer to do another way. This result in very convoluted way to interract with C++. The D phylosophy is to enforce a clean and safe way to do thing (and default initializer definitively goes in that direction) but also open the possibility to get dirty and do whatever is required to do yout hanky panky stuffs. Here is what I suggest : - struct with no default constructor just behave the same way as the did until now. - struct can disable the default constructor as it is possible now. If you create a variable of that type without initialization, you get an error. - struct can define a default constructor. You get the same errors as you get when you disable that default constructor. With some code : struct S { // default constructor defined or disabled } S s; // Error if the default constructor is defined or disabled; S s = S(); // OK if you have a default constructor, error otherwize. S s = S.init; // Call the postblit if a default constructor exists or is disabled That way, we keep the benefit of default initializer for most struct, but open the door for programmers that don't know what fear is about. This modify the behaviour of the struct, but, ATM, the default constructor can be disabled, and it result in inconsistent behaviour (exemple 1 generate error, exemple 3 compile fine and don't call postblit). As the behaviour is different - we losse benefits of default initializers -, we may want to explicit that with a keyword. As you suggested, this is similar with non nullable references and could use the same keyword (and this is a feature that is missing definitively, null check is so easy to forget that it would be great that the compiler help us in the task). This definitively have an impact on severals aspect of D (resising arrays is a good exemple). Thoses would be impacted by the default constructor caracteritics (eventually can throw, become exepensive in computation, etc . . .). We may want to disable thoses operations on such types or limit them in some ways. By the way, bug on opAssign is filled now.

I think it is a reasonable request to allow S s = S(), because you can get the same with static opCall already (more inconvenient though, and no way to get it to work with extern(C++) structs). But I am not sure what to do about the S s = S.init; situation. Calling the postblit is just wrong, because there is no copying going on: S.init is constructed and then _moved_ into s. Move semantics are important, because it allows D code to translate to much faster code than C++98 code that always has to copy and destroy instead of moving.

That make sense. Then, the .init should be a property that call default constructor if it exists. This anyway is important only of we have a default constrctor. Which isn't the idiomatic way in D. But, just as you can get pointer to elements of an array instead of using slice, you should be able to go where you are not supposed to :D
Nov 30 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 11/29/2011 10:09 PM, Andrei Alexandrescu wrote:
 On 11/29/11 11:39 AM, deadalnix wrote:
 Le 29/11/2011 19:52, Andrei Alexandrescu a écrit :
 On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is
 IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it
 working :
 - Default constructor.

No.

No, as "No it will never be done for reason xxx" or as in "No you are wrong and it not necessary, here the way to do : xxx". In both cases, the xxx is the most interesting part :'(

Neither :o). The default initializer that doesn't do any real "work", does not throw, and puts the object in a state without ex-situ ownership has brought D too many benefits to ignore. We should be able to define types that refuse default initialization (a la non-null pointers), but if the default initializer exists, it's good as it is. Andrei

The default initializer can easily be disabled: struct S{ int x; disable this(); disable void[0] init; disable this(this); } Now nobody can do auto x = S.init; But it is still possible to do: S[1] x; I'd have expected that to fail with disabled this(). Is this a bug? If it is a bug, then I think it would be reasonable to allow a default constructor for structs that have disabled default initializers. It would not be different from using static opCall (except that it would actually work in safe code, and conveniently so).
Nov 29 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 11/29/11 2:22 PM, Timon Gehr wrote:
 On 11/29/2011 10:09 PM, Andrei Alexandrescu wrote:
 On 11/29/11 11:39 AM, deadalnix wrote:
 Le 29/11/2011 19:52, Andrei Alexandrescu a écrit :
 On 11/29/11 10:50 AM, deadalnix wrote:
 2/ Use that stract/class as a value type. You can do POD, but also
 define constructor and destructor, copy constructor and overload
 assignement. Anyway, you'll never be able to use proper polymorphism
 here, because it would require virtual destructor at least. This is
 IMO,
 what D's struct should achieve.

Yes.
 The 2/ case is overly used in almost any C++ program. And D struct
 should be able to match them. It wouldn't require much to make it
 working :
 - Default constructor.

No.

No, as "No it will never be done for reason xxx" or as in "No you are wrong and it not necessary, here the way to do : xxx". In both cases, the xxx is the most interesting part :'(

Neither :o). The default initializer that doesn't do any real "work", does not throw, and puts the object in a state without ex-situ ownership has brought D too many benefits to ignore. We should be able to define types that refuse default initialization (a la non-null pointers), but if the default initializer exists, it's good as it is. Andrei

The default initializer can easily be disabled: struct S{ int x; disable this(); disable void[0] init; disable this(this); } Now nobody can do auto x = S.init; But it is still possible to do: S[1] x; I'd have expected that to fail with disabled this(). Is this a bug?

Yes. Andrei
Nov 29 2011
parent reply deadalnix <deadalnix gmail.com> writes:
Le 30/11/2011 03:07, Andrei Alexandrescu a écrit :
 On 11/29/11 2:22 PM, Timon Gehr wrote:
 The default initializer can easily be disabled:

 struct S{
 int x;
  disable this();
  disable void[0] init;
  disable this(this);
 }

 Now nobody can do
 auto x = S.init;


disable void[0] init; Sound hacky as hell. Is it made by design, or is it a consequence of the current compiler implementation ?
 But it is still possible to do:

 S[1] x;

 I'd have expected that to fail with disabled this(). Is this a bug?

Yes. Andrei

It make much more sense that way. At least we can prevent us from getting garbage struct when it comes to interface with C++.
Nov 30 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 11/30/2011 11:57 AM, deadalnix wrote:
 Le 30/11/2011 03:07, Andrei Alexandrescu a écrit :
 On 11/29/11 2:22 PM, Timon Gehr wrote:
 The default initializer can easily be disabled:

 struct S{
 int x;
  disable this();
  disable void[0] init;
  disable this(this);
 }

 Now nobody can do
 auto x = S.init;


disable void[0] init; Sound hacky as hell. Is it made by design, or is it a consequence of the current compiler implementation ?

Built-in properties can be hidden (I am almost sure it is by design), void[0] just means 'field with size 0' and is explicitly allowed by the language specification. disable is by design as well. I orthogonally combined those three features in order to disable the built-in .init property.
 But it is still possible to do:

 S[1] x;

 I'd have expected that to fail with disabled this(). Is this a bug?

Yes. Andrei

It make much more sense that way. At least we can prevent us from getting garbage struct when it comes to interface with C++.

Nov 30 2011
parent reply deadalnix <deadalnix gmail.com> writes:
Le 30/11/2011 13:30, Timon Gehr a écrit :
 On 11/30/2011 11:57 AM, deadalnix wrote:
 Le 30/11/2011 03:07, Andrei Alexandrescu a écrit :
 On 11/29/11 2:22 PM, Timon Gehr wrote:
 The default initializer can easily be disabled:

 struct S{
 int x;
  disable this();
  disable void[0] init;
  disable this(this);
 }

 Now nobody can do
 auto x = S.init;


disable void[0] init; Sound hacky as hell. Is it made by design, or is it a consequence of the current compiler implementation ?

Built-in properties can be hidden (I am almost sure it is by design), void[0] just means 'field with size 0' and is explicitly allowed by the language specification. disable is by design as well. I orthogonally combined those three features in order to disable the built-in .init property.

Yes, I understand that, but the property belong to the struct, not each instance, so it should not work unsless it is static. Am I wrong ?
Nov 30 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 11/30/2011 01:54 PM, deadalnix wrote:
 Le 30/11/2011 13:30, Timon Gehr a écrit :
 On 11/30/2011 11:57 AM, deadalnix wrote:
 Le 30/11/2011 03:07, Andrei Alexandrescu a écrit :
 On 11/29/11 2:22 PM, Timon Gehr wrote:
 The default initializer can easily be disabled:

 struct S{
 int x;
  disable this();
  disable void[0] init;
  disable this(this);
 }

 Now nobody can do
 auto x = S.init;


disable void[0] init; Sound hacky as hell. Is it made by design, or is it a consequence of the current compiler implementation ?

Built-in properties can be hidden (I am almost sure it is by design), void[0] just means 'field with size 0' and is explicitly allowed by the language specification. disable is by design as well. I orthogonally combined those three features in order to disable the built-in .init property.

Yes, I understand that, but the property belong to the struct, not each instance, so it should not work unsless it is static. Am I wrong ?

Interesting point. disable just disables a symbol. This precedes any type checks. It works because it is not possible to overload a symbol based on 'static'.
Nov 30 2011
prev sibling parent "Martin Nowak" <dawg dawgfoto.de> writes:
On Tue, 29 Nov 2011 19:50:10 +0100, deadalnix <deadalnix gmail.com> wrot=
e:

 Le 29/11/2011 18:08, Martin Nowak a =C3=A9crit :
 On Tue, 29 Nov 2011 16:46:55 +0100, deadalnix <deadalnix gmail.com>  =


 wrote:
 Notably, it's very difficult to map a C++ POD class with a default
 constructor and copy constructor/assignement overload. struct doesn'=



 Don't want to be picky, but a struct with default constructor is not =


 POD.
 And yes it is not possible to map all C++ concepts to D.

OK, usage of POD was not the right term. But as matter of fact, C++ =

 gives you 2 general direction to use structs/classes :
 1/ You make your struct/class non copyable (making copy constructor an=

 assignement operator private for exemple), the destructor virtual and =

 use it as a polymorphic type. This is what D's class is supposed to do=

 2/ Use that stract/class as a value type. You can do POD, but also  =

 define constructor and destructor, copy constructor and overload  =

 assignement. Anyway, you'll never be able to use proper polymorphism  =

 here, because it would require virtual destructor at least. This is IM=

 what D's struct should achieve.

 The 2/ case is overly used in almost any C++ program. And D struct  =

 should be able to match them. It wouldn't require much to make it  =

 working :
   - Default constructor.
   - The hability to define opAssign for it's own type if this(this) is=

 disabled.

 Today we have 2 options in D : go for struct and get an error prone  =

 binding (it's very easy to get a garbage struct, because you cannot  =

 enforce that you'll go throw the constructor, and you cannot map copy =

 constructor, even with additionnal C++ code).

 Or you can go final class, but you don't have a value type anymore and=

 it become quite hard to pass the object to/from C++, because of the  =

 header of the object. If you get one from C++, you need the rewrap it =

 a object on the D side, but . . . the copy constructor isn't mappable.=

 So you need to play ping pong between D and C++ to allocated the D  =

 object, then go back to C++ to copy the data using the proper copy cod=

 and then go back to D to do something with that. Plus you need an heap=

 allocation (which isn't inexpansive ATM, because of the lock in it, an=

 cannot compete with stack anyway).

The interfacing of C/C++ structs is limited to compatible memory layout.= It might seem arbitrary restrictive, but from what you describe you could directly use a shared_ptr<T> in D code. This is likely too much, as it conflicts with the semantic differences you observe. As you have to redeclare a POD anyhow you could make it a two face = structure, i.e. implementing some methods on both sides which might also gives you = = more efficient code. P.S.: There is also a bug of passing struct values for x86_64. http://d.puremagic.com/issues/show_bug.cgi?id=3D5570
 allow for default constructor and copy constructor isn't mappable
 using posblit. final class imply an overhead, and are references typ=



 (so cannot be passed by value).



 inexistent
 (I'm not aware of any language that achieves this).

 I've recently posted a feasible solution to allocate C++ classes usin=


 the
 D garbage collector and profit from automatic lifetime management.
 https://gist.github.com/1391734

 Given that all bugs get sorted out, one can expect three mechanisms t=


 work.

 - Calling free C++ functions and probably non-virtual methods
 - Pass POD data forth and back
 - Call virtual methods of classes with known vtable layout

 Some more things as calling namespace function or certain templates  =


 could
 probably be provided by a library. But it should suffice to provide z=


 overhead
 interfacing to most C++ code.
 Interfacing QT with it's heavy use of virtual calls,  =


 multiple-inheritance
 and a custom pre-processor will require an additional simplifying
 wrapper layer
 on the C++ side.

 martin

I did had a look at that code just befor you posted (somebody mention =

 that on irc). This is a nice piece of code. But clearly solve another =

 problem that the one I'm talking about.

 If your are interested I wrote something about starting thread on the =

 C++ side but remaining compatible with D (so you can call D code from =

 the C++ thread) here :  =

 http://www.deadalnix.42/2011/11/24/interfacing-d-with-c-start-new-thre=

 (require 42registry).

Nov 29 2011