Re: Polymorphism? Passing arguments
ok, thanks you very much for the information.
Re: Polymorphism? Passing arguments
On Saturday, November 04, 2017 01:52:06 Martin via Digitalmars-d-learn wrote: > Thank you for the answer > > On Saturday, 4 November 2017 at 01:35:41 UTC, Adam D. Ruppe wrote: > > Why are these ref? > > Just taking ref away from both of those will likely fix your > > problems. > > because without it i get the error "Program exited with code -11" > > The thing is, somwhere deeper in `setRelation` i call two > functions: > ``` > public void addChild(ref Node child) { >this.children ~= &child; > } > > public void setParent(ref Node parent) { >this.parent = &parent; > } > ``` Okay, classes are reference types in D just like they are in Java or C#. They do not live on the stack like they do in C++ (for that, you'd use a struct, which has no inheritance). Class references are basically pointers. Taking the address of a class reference is taking the address of the variable on the stack. If T is a class, then T foo = getSomeT(); T* bar = &foo; in D would be more or less equivalent to this in C++: T* foo = getSomeT(); T** bar = &foo; By making the parameter ref, you are then getting the address of the class reference in the caller, whereas without it, you're getting the address of the class reference of the callee, and that then goes away when the function exits - which is why things blow up on you. But they'll blow up the same way once the variable in the class reference that you passed in goes out of scope, and you try to use the addresses that you stored. If you ever use & with a class in D, you're almost certainly doing something wrong. If typeof(this.parent) is Node, then setParent should be able to just accept the Node without ref and assign it to this.parent, and this.parent is then going to be pointing to the same object that the Node you passed to setParent was pointing to. There should be no need for pointers or &. I would suggest that you read this online book: http://ddili.org/ders/d.en/index.html It should help you with all of the basic stuff in D like this. If you want to know about classes specifically, then you can skip straight to the chapter on classes: http://ddili.org/ders/d.en/class.html but I expect that you'll benefit from reading the whole thing. - Jonathan M Davis
Re: Polymorphism? Passing arguments
Thank you for the answer On Saturday, 4 November 2017 at 01:35:41 UTC, Adam D. Ruppe wrote: Why are these ref? Just taking ref away from both of those will likely fix your problems. because without it i get the error "Program exited with code -11" The thing is, somwhere deeper in `setRelation` i call two functions: ``` public void addChild(ref Node child) { this.children ~= &child; } public void setParent(ref Node parent) { this.parent = &parent; } ```
Re: Polymorphism? Passing arguments
On Saturday, November 04, 2017 01:22:05 Martin via Digitalmars-d-learn wrote: > I have a interface > `interface Node {...}` > > and some classes implementing Node: > ``` > class Text : Node {...} > class Element : Node {...} > ``` > and a function like this: > `public void setRelation(ref Node parent , ref Node child) {...}` > > if i do this it works: > ``` > Node root = new Element("root"); > Node text = new Text("blah"); > setRelation(root , text); > ``` > > but this does not: > ``` > Node root = new Element("root"); > setRelation(root , new Text("blah")); > ``` > > >Error: function Nodes.setRelation (ref Node parent, ref Node > >child) is not callable using argument types (Node, Text) > > Why is this? Text implements Node. This is how i do it in other > Languages - How can would be this possible in D? The problem really doesn't have anything to do with the types involved. It has to do with ref. ref only accepts lvalues, not rvalues. So, you can't pass it the result of new or the result of any function that returns by value. The first example works, because you're passing variables, which are lvalues. So, if you remove ref from parent and child, then you won't have any problems like this, and unless you're planning on altering which objects parent and child refer to, there's really no reason to have them be marked with ref. - Jonathan M Davis
Re: Polymorphism? Passing arguments
On Saturday, 4 November 2017 at 01:22:05 UTC, Martin wrote: `public void setRelation(ref Node parent , ref Node child) Why are these ref? A lot of people coming from C++ use ref in places you shouldn't use it in D. Remember, in D, a class object is implicitly ref, so doing `ref Object` is more like `Object**` or `Object&&` - often more direction than you need and want. Just taking ref away from both of those will likely fix your problems. setRelation(root , new Text("blah")); In this case, it definitely will. An explicit ref in D must refer to a variable name, not just an object. Since `new Text()` has no variable name, it cannot be ref. Why is this? Text implements Node. This is how i do it in other Languages - How can would be this possible in D? But, even if it were legal to do what you're trying on ref semantics, this would still be broken polymorphism! Consider the following: Text text = new Text(); Node n = text; // legal, Text implements Node n = new Element(); // also legal, Element impls Node too bt: Text text = new Text(); Node* n = &text; // subtly different than above... *n = new Element(); // ...because this would be bad news // what is text now? If the compiler allowed that pointer (or the ref, same deal), you would have overwritten a Text object with an Element, breaking the type system. This is also the reason why a Text[] will not cast to a Node[], even though an individual Text is a Node.
Polymorphism? Passing arguments
I have a interface `interface Node {...}` and some classes implementing Node: ``` class Text : Node {...} class Element : Node {...} ``` and a function like this: `public void setRelation(ref Node parent , ref Node child) {...}` if i do this it works: ``` Node root = new Element("root"); Node text = new Text("blah"); setRelation(root , text); ``` but this does not: ``` Node root = new Element("root"); setRelation(root , new Text("blah")); ``` Error: function Nodes.setRelation (ref Node parent, ref Node child) is not callable using argument types (Node, Text) Why is this? Text implements Node. This is how i do it in other Languages - How can would be this possible in D?
Re: private keyword dont appear to do anything
On Fri, Nov 03, 2017 at 05:59:20PM -0600, Jonathan M Davis via Digitalmars-d-learn wrote: > On Friday, November 03, 2017 16:32:52 H. S. Teoh via Digitalmars-d-learn > wrote: > > Perhaps the solution is to go the > > one-overload-set-per-file route, with std/algorithm/package.d > > basically importing everything underneath. :-P > > > > (Shhh, don't tell Andrei, or we'll get another lecture about wasting > > time on worthless things while more important things are left to > > do.) > > Actually, when Daniel and I were trying to talk Walter into adding the > package.d feature so that std.datetime could be split up without > breaking code, Walter made a comment about how he didn't see any > problem with there being a function per module. So, he might be on > board with code arrangements along those lines, but I have no idea > about Andrei. I got chastised by Andrei for doing the std.algorithm split. He only conceded after I stated that I couldn't run the std.algorithm unittests on my PC anymore because it was taking up GBs of memory. Based on that I'm assuming he would likely be opposed to yet another refactoring of std.algorithm. :-D > Personally, I think that splitting stuff up that far makes it a pain > to deal with, even if it might help the implementation sometimes. It's > already really annoying that I have to figure out which module > something in std.algorithm is in now, because the style check junk > that has been added to Phobos requires that you not only use selective > imports but that you use the module that it's directly in, so you > can't do something like > > import std.algorithm : map; > > but instead have to go figure out which module it's currently living > in and add that after std.algorithm. If we split everything into its own module, presumably the module would be named after the function itself, and would inherit directly from the top-level std.algorithm package. So it would be a simple matter of going to std/algorithm/${function_name}.d to find the code, which arguably would be *simpler* than it is today. But again, I'm not seriously proposing this, and I doubt we'd actually do it anyway. The sheer amount of effort involved, plus potential user code breakage (explicit imports of std.algorithm.searching, for example, would break, unless we keep searching.d around as just a bunch of public imports, which is kinda ugly), yielding only marginal benefits. I just don't see W & A approving of something like that. [...] > Where you risk running into serious problems is where you have a large > module full of interdependent stuff, because then it's all highly > coupled and hard to keep track of, so it becomes hard to understand > and maintain. You can have the same problems across modules, but when > you split stuff up across modules, it tends to force you to think > about things differently so that you don't make everything so highly > coupled - though a bad programmer (or a good programmer having a bad > day) can make any code a mess. [...] "Real Programmers can write assembly code in any language." :-D T -- Winners never quit, quitters never win. But those who never quit AND never win are idiots.
Re: private keyword dont appear to do anything
On Friday, November 03, 2017 16:32:52 H. S. Teoh via Digitalmars-d-learn wrote: > Perhaps the solution is to go the > one-overload-set-per-file route, with std/algorithm/package.d basically > importing everything underneath. :-P > > (Shhh, don't tell Andrei, or we'll get another lecture about wasting > time on worthless things while more important things are left to do.) Actually, when Daniel and I were trying to talk Walter into adding the package.d feature so that std.datetime could be split up without breaking code, Walter made a comment about how he didn't see any problem with there being a function per module. So, he might be on board with code arrangements along those lines, but I have no idea about Andrei. Personally, I think that splitting stuff up that far makes it a pain to deal with, even if it might help the implementation sometimes. It's already really annoying that I have to figure out which module something in std.algorithm is in now, because the style check junk that has been added to Phobos requires that you not only use selective imports but that you use the module that it's directly in, so you can't do something like import std.algorithm : map; but instead have to go figure out which module it's currently living in and add that after std.algorithm. Of course, I also don't generally have a problem with large modules. They _can_ become large enough to become a problem, but I've found that I have a much higher tolerance for how much goes in a single file than many of the D devs seem to have. IMHO, the main thing that starts causing problems with large modules is when you start doing stuff like using attribute labels like @safe: or attribute blocks like @safe { } because then it becomes difficult to know which attributes actually apply to a piece of code. Most stuff is self-contained enough that having a bunch of stuff in a single module frequently isn't a real problem. So, if they're related enough, I have no problem with it. But good organization is arguably difficult to get right and highly subjective - just like naming stuff is. Where you risk running into serious problems is where you have a large module full of interdependent stuff, because then it's all highly coupled and hard to keep track of, so it becomes hard to understand and maintain. You can have the same problems across modules, but when you split stuff up across modules, it tends to force you to think about things differently so that you don't make everything so highly coupled - though a bad programmer (or a good programmer having a bad day) can make any code a mess. - Jonathan M Davis
Re: private keyword dont appear to do anything
On Fri, Nov 03, 2017 at 04:30:21PM -0600, Jonathan M Davis via Digitalmars-d-learn wrote: > On Friday, November 03, 2017 14:52:22 H. S. Teoh via Digitalmars-d-learn > wrote: [...] > > Arguably, many of these large flat files ought to be split up into > > smaller files. For example, std.algorithm.* and std.range.* all > > tend to be conglomerations of basically-independent groups of > > structs and functions. Iota and Cycle never interact with each > > other, and neither of them interacts with Recurrence, yet these all > > sit in the same file. > > > > Seems to me like a typical case of low cohesion, which, according to > > the ideals of encapsulation, ought to be grounds for splitting up > > the file into self-contained parts. > > > > But of course, there are pragmatic reasons for the way things > > currently are. > > If you take that to the extreme, you just end up with a function per > module, which is pretty ridiculous IMHO (though that may be what you > mean by pragmatic reasons). It's not that ridiculous if you consider that some of the more heavily-used Phobos functions are actually not individual functions, but overload sets. I know we have been trying to merge some of the unnecessary overload sets for other reasons, but some of these overload sets can get pretty big. Compound that with the long string of unittests associated with each overload, that has accumulated from a long string of bug fixes, etc., and you have pretty good justification for keeping just that single overload set in its own file, together with its associated unittests, and potentially also other paraphrenalia like enums or other declarations used by the overload set, but not used anywhere else. > And really, free functions like that are exactly the sort of places > where encapsulation tends not to matter much, because there's nothing > to encapsulate beyond the guts of the functions themselves, which are > already encapsulated. Arguably, once a function grows past a certain length, it's time to break it down into more manageable pieces. Having a function sit in its own file gives you a nice working space for this sort of refactoring, without worrying about namespace conflicts with unrelated code. Still, I agree that some degree of judgment is involved here. If we're talking about a simple function that will never grow past 5-10 lines, it does seem a little pointless to keep it in its own file, just to adhere to some ideal of encapsulation. But IME, with Phobos code even simple functions eventually grow into multi-page monsters over time, once you start adding type-specific specializations to deal with performance issues and the like. Just look at std.algorithm.searching.find, for example. Several different overloads, and static if blocks within an overload, sometimes on the lengthy side depending on the specific optimization being implemented. Arguably we should factor out some of the static if blocks or overloads into separate private functions for easier future maintenance / management if more specializations are added, or we need to balance between different optimizations based on different factors. Static-if / else blocks just aren't very conducive to this sort of thing. And being able to do this in a file dedicated to .find would be cleaner than having to do surgery in a 4600-line file (and having to deal with potential merge conflicts with other unrelated changes to the same file -- though git is so good at this that one generally doesn't run into much of a problem). > The situation is very different from something like std.container > where you have types which have member variables which could be > protected from access by other stuff in their modules if private > worked differently. Well, std.container *has* been split into submodules per container type. I think that's a much better organization than in std.algorithm.*. > Figuring out a good way to organize a bunch of free functions is > difficult (as evidenced by the fact that plenty of folks have a hard > time remembering what is where inside of std.algorithm and std.range), > but that's really not an encapsulation problem, just a code > organization problem. [...] Perhaps the solution is to go the one-overload-set-per-file route, with std/algorithm/package.d basically importing everything underneath. :-P (Shhh, don't tell Andrei, or we'll get another lecture about wasting time on worthless things while more important things are left to do.) T -- All problems are easy in retrospect.
Re: private keyword dont appear to do anything
On Friday, November 03, 2017 14:52:22 H. S. Teoh via Digitalmars-d-learn wrote: > On Fri, Nov 03, 2017 at 05:43:55PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: > > On 11/3/17 5:08 PM, Nathan S. wrote: > > > On Friday, 3 November 2017 at 20:01:27 UTC, Jonathan M Davis wrote: > > > > Most folks are surprised by this behavior > > > > > > I found it surprising at first but now any other way seems absurd to > > > me. None of the benefits of data encapsulation apply to code > > > written five lines away in the same file. > > > > I also enjoy the mechanism, but I have to call this out as incorrect. > > Encapsulation is about being able to prove to yourself exactly how an > > object's private data can possibly be manipulated. It's not just 5 > > lines away, it's the whole file you have to review. > > > > If you have large flat files like Phobos, then encapsulation is > > essentially impossible to review. > > [...] > > Arguably, many of these large flat files ought to be split up into > smaller files. For example, std.algorithm.* and std.range.* all tend to > be conglomerations of basically-independent groups of structs and > functions. Iota and Cycle never interact with each other, and neither > of them interacts with Recurrence, yet these all sit in the same file. > > Seems to me like a typical case of low cohesion, which, according to the > ideals of encapsulation, ought to be grounds for splitting up the file > into self-contained parts. > > But of course, there are pragmatic reasons for the way things currently > are. If you take that to the extreme, you just end up with a function per module, which is pretty ridiculous IMHO (though that may be what you mean by pragmatic reasons). And really, free functions like that are exactly the sort of places where encapsulation tends not to matter much, because there's nothing to encapsulate beyond the guts of the functions themselves, which are already encapsulated. The situation is very different from something like std.container where you have types which have member variables which could be protected from access by other stuff in their modules if private worked differently. Figuring out a good way to organize a bunch of free functions is difficult (as evidenced by the fact that plenty of folks have a hard time remembering what is where inside of std.algorithm and std.range), but that's really not an encapsulation problem, just a code organization problem. - Jonathan M Davis
Re: How to use containers in lock based concurrency
On Friday, November 03, 2017 21:23:02 Nathan S. via Digitalmars-d-learn wrote: > Is this advice from 2015 outdated? I found it while I was > wrestling with shared data structures, and after reading I > stopped doing that. > > https://p0nce.github.io/d-idioms/#The-truth-about-shared > > >The truth about shared > >It's unclear when and how shared will be implemented. > >Virtually noone use shared currently. You are better off > >ignoring it at this moment. That advice was wrong when it was written. Plenty of folks don't understand how to use shared properly, and there are lots of folks who cop out and use __gshared instead, but shared _does_ work, even if it's annoying to use, and __gshared is only intended for C globals. Using it on D objects is just begging for problems, because the type system will treat them as thread-local even though they're not. So, using __gshared can lead to subtle, hard-to-find bugs that shared code won't have. One of the problems with shared has been that it hasn't been used where it should be (e.g. core.sync.mutex didn't use it, but I think that that's been fixed now), making it harder to write shared code than it should be. However, a lot of it just comes down to the fact that everyone balks at the fact that shared requires casting to use properly. You rarely simply call functions on shared objects, because if you did, there would be race conditions. Rather, the way that shared should normally be used is essentially: shared(MyObject) mySharedObject; // ... synchronized(mutexForMySharedObject) { auto myObj = cast(MyObject)mySharedObject; // do stuff with myObj // ... // make sure that at this point, there are no thread-local references // to mySharedObject which have escaped. } // And here, after the lock is released, we should just have the shared // reference again. It would be nice if we had a way to use shared that didn't require explicit casting like that, but that code is essentially would you would do in a C++ program that was correctly dealing with objects shared across threads except that the C++ program wouldn't have to cast away shared, because it puts everything in shared memory whether it's actually used on multiple threads or not, and its type system doesn't help you segregate code that operates on objects that are used across threads. The annoyances with D's shared come from it preventing you from doing stuff that actually isn't thread-safe and requiring you to go to extra effort to then use the objects. What we end up with is a bit like @safe and @trusted in that most of the code does not use shared objects and has any shared objects that it does have explicitly marked that way, and then there are small sections of code where you do the risky thing that requires scrutiny where you cast away shared and operate on it as if it were thread-local - of course, with a lock to ensure that it's actually safe to operate on the object as thread-local, but all of that requires that the programmer manually verify it rather than the compiler being able to guarantee it for you like it can be preventing you from doing stuff with shared objects that isn't thread-safe. In principle, synchronized classes as described in TDPL are supposed to at least partially solve the casting problem, because they would guarantee that the objects don't escape from the synchronized class, allowing the compiler to safely remove the outer layer of shared on member variables so that you get that automatic cast - but only for the outer layer of shared (since they can't guarantee that no other references to the data exist beyond the outer layer). So, synchronized classes would only partially solve the problem. But regardless, we don't actually have synchronized classes at the moment - just synchronized functions - so we don't get even that much right now. There is occasionally talk about overhauling shared in order to improve it, but I think that most of that has to do with better defining spec-wise what's going on with the memory model. We may very well be able improve some of how shared is used as well, but fundamentally, it's very difficult to guarantee that no other references could be mucking around with an object in a given piece of code such that the compiler can automatically cast away shared for you. As with @trusted, it requires the programmer to do the right thing and verify that they're doing the right thing. - Jonathan M Davis
Re: private keyword dont appear to do anything
On Fri, Nov 03, 2017 at 05:43:55PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: > On 11/3/17 5:08 PM, Nathan S. wrote: > > On Friday, 3 November 2017 at 20:01:27 UTC, Jonathan M Davis wrote: > > > Most folks are surprised by this behavior > > > > I found it surprising at first but now any other way seems absurd to > > me. None of the benefits of data encapsulation apply to code > > written five lines away in the same file. > > I also enjoy the mechanism, but I have to call this out as incorrect. > Encapsulation is about being able to prove to yourself exactly how an > object's private data can possibly be manipulated. It's not just 5 > lines away, it's the whole file you have to review. > > If you have large flat files like Phobos, then encapsulation is > essentially impossible to review. [...] Arguably, many of these large flat files ought to be split up into smaller files. For example, std.algorithm.* and std.range.* all tend to be conglomerations of basically-independent groups of structs and functions. Iota and Cycle never interact with each other, and neither of them interacts with Recurrence, yet these all sit in the same file. Seems to me like a typical case of low cohesion, which, according to the ideals of encapsulation, ought to be grounds for splitting up the file into self-contained parts. But of course, there are pragmatic reasons for the way things currently are. T -- Государство делает вид, что платит нам зарплату, а мы делаем вид, что работаем.
Re: private keyword dont appear to do anything
On 11/3/17 5:08 PM, Nathan S. wrote: On Friday, 3 November 2017 at 20:01:27 UTC, Jonathan M Davis wrote: Most folks are surprised by this behavior I found it surprising at first but now any other way seems absurd to me. None of the benefits of data encapsulation apply to code written five lines away in the same file. I also enjoy the mechanism, but I have to call this out as incorrect. Encapsulation is about being able to prove to yourself exactly how an object's private data can possibly be manipulated. It's not just 5 lines away, it's the whole file you have to review. If you have large flat files like Phobos, then encapsulation is essentially impossible to review. -Steve
Re: private keyword dont appear to do anything
On Fri, Nov 03, 2017 at 09:08:56PM +, Nathan S. via Digitalmars-d-learn wrote: > On Friday, 3 November 2017 at 20:01:27 UTC, Jonathan M Davis wrote: > > Most folks are surprised by this behavior > > I found it surprising at first but now any other way seems absurd to > me. None of the benefits of data encapsulation apply to code written > five lines away in the same file. This is a good point. :-) Though in practice, source files do tend to get long... I've had to work with source files over 8000+ lines long, and having encapsulation between two distant parts of the file can be useful. However, even then, one can argue that any benefits of encapsulation you may have are already negated by the very-not-encapsulated practice of an 8000-line long source file, so the point is moot anyway. T -- Don't get stuck in a closet---wear yourself out.
Re: How to use containers in lock based concurrency
Is this advice from 2015 outdated? I found it while I was wrestling with shared data structures, and after reading I stopped doing that. https://p0nce.github.io/d-idioms/#The-truth-about-shared The truth about shared It's unclear when and how shared will be implemented. Virtually noone use shared currently. You are better off ignoring it at this moment.
Re: private keyword dont appear to do anything
On Friday, 3 November 2017 at 20:01:27 UTC, Jonathan M Davis wrote: Most folks are surprised by this behavior I found it surprising at first but now any other way seems absurd to me. None of the benefits of data encapsulation apply to code written five lines away in the same file.
Re: private keyword dont appear to do anything
On Friday, November 03, 2017 13:43:15 rikki cattermole via Digitalmars-d- learn wrote: > Visibility modifiers like private, and public are to the module not the > scope. > > "Symbols with private visibility can only be accessed from within the > same module." > > This is how module based languages work, a bit more useful then to the > scope approach IMO. An easy mistake to make. > > https://dlang.org/spec/attribute.html#visibility_attributes To be fair, there are times where it would arguably be desirable to restrict private to a struct or class, so it's not all wonderful, but it does mean that we don't have to have the extra complication of friend functions like C++ does (which I believe is the biggest motivation for it). And if a module is so large that you can't make sure that nothing is accessing private struct or class members when it shouldn't, then the module is probably overly large and/or complicated. Most folks are surprised by this behavior, and occasionally, they complain about it, but in practice, the only real problem that I'm aware of is that you can sometimes write unit tests which work just because they're in the module, and the code doesn't work when used outside of the module. But even that tends to be only an occasional problem. - Jonathan M Davis
Re: How to use containers in lock based concurrency
On Friday, 3 November 2017 at 12:42:29 UTC, ANtlord wrote: Hello! I can't get how to use double linked list in concurrency. Please help. ... I get a compile error onlineapp.d(8): Error: template std.container.dlist.DList!string.DList.insertFront cannot deduce function from argument types !()(string) shared, One Does Not Simply get the non-shared object and use in the shared code. (/Boromir mode) For me, it was useful to read this: http://www.informit.com/articles/article.aspx?p=1609144&seqNum=11
Re: COM/OLE advanced questions
On Friday, 3 November 2017 at 12:24:43 UTC, Guillaume Piolat wrote: On Friday, 3 November 2017 at 10:50:27 UTC, Kagamin wrote: It only looks at the name. I'll test if that name needs to be "IUnknown" or the exact "core.sys.windows.unknwn.IUnknown", since I'm in @nogc and not necessarily on Windows, so I can't inherit from core.sys.windows.unknwn.IUnknown (but still need a COM-like layout). The answer is that "IUnknown" is all that is needed, no matter what the fully qualified name.
Re: private keyword dont appear to do anything
On Friday, 3 November 2017 at 12:43:15 UTC, rikki cattermole wrote: Visibility modifiers like private, and public are to the module not the scope. "Symbols with private visibility can only be accessed from within the same module." This is how module based languages work, a bit more useful then to the scope approach IMO. An easy mistake to make. https://dlang.org/spec/attribute.html#visibility_attributes thank you
Re: COM/OLE advanced questions
On Friday, 3 November 2017 at 12:20:43 UTC, Guillaume Piolat wrote: On Friday, 3 November 2017 at 02:30:59 UTC, evilrat wrote: My guess it will work fine when derive from any extern(Windows) interface(that's right, not class) that has base 3 methods(AddRef, Release, QueryInterface) I'll test that scenario and see if the layout is the same. And you were right in this.
Re: COM/OLE advanced questions
Answering my own questions: On Thursday, 2 November 2017 at 14:22:56 UTC, Guillaume Piolat wrote: Question 1. Is it mandatory to inherit from core.sys.windows.unknwn.IUnknown, or just having an interface named "IUnknown" validate it for being a COM interface? Deriving from an interface named "IUnknown", in whatever module, with whatever actual methods, make the compiler consider it a "COM interface", which applies semantic restrictions. The actual layout is _separated_ from the compiler considering it as a "COM interface", and one can achieve the exact desired layout with a IUnknown-like interface named in other way. One can test this with `delete interfaceInstance`. The only layout effect of having the compiler consider it like COM interface, is that derived class will become "COM classes" whose only effects seems to be extern(System) as default linkage type. So: you don't need the compiler to follow COM ABI, it just makes it easier. Question 2. If this fails, may I emulate COM vtable layout with extern(C++) class? I wonder what the exact differences are anyway between extern(C++) and the special IUnknown. extern(C++) is indeed very flexible, with no virtual methods, whereas COM objects will have at least 8. However this doesn't seem needed. Question 3. It seems I can inherit both from A D object and a COM interface. What will be the choosen layout? Should not be a problem. The problem I had was my inability to override a base class methods since I forgot extern(D). This problem is talked about in the spec: https://dlang.org/spec/interface.html#com-interfaces
How to use containers in lock based concurrency
Hello! I can't get how to use double linked list in concurrency. Please help. Providing code import std.stdio; import std.container; synchronized class SocksQueue { private shared(DList!string) _queue; public void f(string data) { this._queue.insertFront(data); } } void main(string[] args) { } I get a compile error onlineapp.d(8): Error: template std.container.dlist.DList!string.DList.insertFront cannot deduce function from argument types !()(string) shared, candidates are: /dlang/dmd/linux/bin64/../../src/phobos/std/container/dlist.d(441): std.container.dlist.DList!string.DList.insertFront(Stuff)(Stuff stuff) https://run.dlang.io/gist/3afff560fe3b2f439272c3ee3adcebd0?compiler=dmd
Re: private keyword dont appear to do anything
Visibility modifiers like private, and public are to the module not the scope. "Symbols with private visibility can only be accessed from within the same module." This is how module based languages work, a bit more useful then to the scope approach IMO. An easy mistake to make. https://dlang.org/spec/attribute.html#visibility_attributes
private keyword dont appear to do anything
hello, being new to D i assumed that the private keyword would work as in C++, but writing this code, i excepted it to throw an error at compile time, it appear to not doing anything, is there something i am doing wrong ? -- import std.stdio; class Foo { private int id = 10; } struct Bar { private int id = 20; } void main() { auto foo = new Foo; Bar bar; foo.id = 15; bar.id = 25; writeln(foo.id); writeln(bar.id); } // RDMD OUTPUT // 15 // 25
Re: COM/OLE advanced questions
On Friday, 3 November 2017 at 10:50:27 UTC, Kagamin wrote: It only looks at the name. I'll test if that name needs to be "IUnknown" or the exact "core.sys.windows.unknwn.IUnknown", since I'm in @nogc and not necessarily on Windows, so I can't inherit from core.sys.windows.unknwn.IUnknown (but still need a COM-like layout).
Re: COM/OLE advanced questions
On Friday, 3 November 2017 at 02:30:59 UTC, evilrat wrote: You can't(or maybe you can but that is not a true COM). COM is Windows tech. It is backed up by OLE or whatever server it is. What happens is that I translate a SDK which provides "COM-like" objects, on Windows and Mac (claiming ABI compatibility) and I'd like to know if I'll be able to use the COM facilities in D. No class will need registering. My guess it will work fine when derive from any extern(Windows) interface(that's right, not class) that has base 3 methods(AddRef, Release, QueryInterface) I'll test that scenario and see if the layout is the same.
Re: COM/OLE advanced questions
On Thursday, 2 November 2017 at 14:22:56 UTC, Guillaume Piolat wrote: Question 1. Is it mandatory to inherit from core.sys.windows.unknwn.IUnknown, or just having an interface named "IUnknown" validate it for being a COM interface? If yes, then how am I supposed to use COM interfaces in other OSes? core.sys.windows.unknwn.IUnknown is defined under version(Windows). I suppose you will need a bunch of definitions. One strange thing is that core.sys.windows defines GUID with alignment 1, which I expect to differ on other platforms. I wonder what the exact compiler hook is. I only looks at the name. Question 2. If this fails, may I emulate COM vtable layout with extern(C++) class? I wonder what the exact differences are anyway between extern(C++) and the special IUnknown. Depends on implementation. XPCOM uses straight C++ ABI on linux, so look what you want to work with. Question 3. It seems I can inherit both from A D object and a COM interface. What will be the choosen layout? Shouldn't matter, interface defines ABI, how it's implemented is irrelevant - that's the very idea behind COM. It's actually legal to implement interfaces with composition, the caller still doesn't see anything.