digitalmars.D.learn - Incomplete types question
- NoUseForAName (13/13) Jul 07 2014 In C my favorite way of achieving encapsulation is to use
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (47/59) Jul 07 2014 1) Put the opaque type and its functions into a .di file:
- NoUseForAName (13/17) Jul 08 2014 Thanks.. but this is awkward. I expected there to be keywords to
- bearophile (6/9) Jul 08 2014 I suggest you to not give up yet. About 100% of the times there
- NoUseForAName (15/19) Jul 08 2014 So I could just put..
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (24/41) Jul 08 2014 They are optional, for those situations when you don't want to
- bearophile (5/17) Jul 08 2014 I still don't understand the point of doing this. Is @disable
- NoUseForAName (2/16) Jul 08 2014 Thanks, that is what I was looking for.
- bearophile (4/5) Jul 08 2014 Why do you need a public pointer type but private struct type?
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (6/11) Jul 08 2014 (Also known as PIMPL.)
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (11/33) Jul 08 2014 Addendum: You also need to protect the members of MyStructImpl,
- NoUseForAName (2/9) Jul 08 2014 Thanks again.
- bearophile (7/8) Jul 08 2014 [...]
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (3/10) Jul 08 2014 I should have first asked what the need was.
- bearophile (5/9) Jul 07 2014 Probably in D you can archive something similar with different
In C my favorite way of achieving encapsulation is to use incomplete types. The module header contains the definition of an incomplete type and the prototypes for the public functions which operate on it. I have read D has incomplete types too however D does not have headers and as a C guy I do not know how to implement this scheme without a .h/.c separation. As I said, in C I put the incomplete declaration in the header while keeping the complete declaration private to the module. How do I do this in D? I mean type is complete within the module itself (and thus can be instantiated there) but incomplete for clients (i.e. other modules) i.e. instantiating or modifying data of that type directly is impossible. P.S.: It seems D lingo for incomplete types is "opaque types".
Jul 07 2014
On 07/07/2014 09:44 PM, NoUseForAName wrote:In C my favorite way of achieving encapsulation is to use incomplete types. The module header contains the definition of an incomplete type and the prototypes for the public functions which operate on it. I have read D has incomplete types too however D does not have headers and as a C guy I do not know how to implement this scheme without a .h/.c separation. As I said, in C I put the incomplete declaration in the header while keeping the complete declaration private to the module. How do I do this in D? I mean type is complete within the module itself (and thus can be instantiated there) but incomplete for clients (i.e. other modules) i.e. instantiating or modifying data of that type directly is impossible. P.S.: It seems D lingo for incomplete types is "opaque types".1) Put the opaque type and its functions into a .di file: // deneme.di module deneme; struct S; S * makeS(int i); void useS(S * s); 2) Put the implementation in its .d file: // deneme.d module deneme; import std.stdio; struct S { int i; void foo() { writefln("Executing foo() for %s", this); } } S * makeS(int i) { return new S(i); } void useS(S * s) { s.foo(); } 3) Compile the implementation as a library (just a .o in this case): $ dmd deneme.d -c (That will create the file deneme.o) 4) Write a client program that uses the interface. (Make sure that only deneme.di is visible to the client (not deneme.d).) // main.c import deneme; void main() { S * s = makeS(42); useS(s); } 5) Compile (and link) the client program and the library to make the program: $ dmd main.d deneme.o (That will create the executable 'main'.) 6) Run the program: $ ./main Executing foo() for S(42) Ali
Jul 07 2014
On Tuesday, 8 July 2014 at 06:28:51 UTC, Ali Çehreli wrote:On 07/07/2014 09:44 PM, NoUseForAName wrote:[snip][snip]3) Compile the implementation as a library (just a .o in this case):Thanks.. but this is awkward. I expected there to be keywords to declare type declarations public or private. Also using a separate .di file means I lose the whole advantage of not having to use header files. My idea here was basically to use D as a "better C", you know without the annoying stuff like header files / no real modules. Seems C is actually superior for what I want to do. .di vs. h is no real advantage, and in C I do not need to move the implementation into a library to stop other modules from using the type directly. Again, thanks for the detailed explanation but I guess I am going to stick with C for this.
Jul 08 2014
NoUseForAName:Thanks.. but this is awkward. I expected there to be keywords to declare type declarations public or private.The keywords are "public" and "private".I guess I am going to stick with C for this.I suggest you to not give up yet. About 100% of the times there are equivalent or better ways to do something of C in D. Bye, bearophile
Jul 08 2014
On Tuesday, 8 July 2014 at 09:08:30 UTC, bearophile wrote:NoUseForAName:So I could just put.. public struct S; private struct S { int i; } .. in the .d file and that would work? I mean I expected something like this but then why would Ali post such a complex solution? Also side question. What are these .di files? D propaganda radio told me that D does not need header files because it has a real module system (like e.g. Pascal or Go) yet in the solution Ali posted these .di files seem to be.. pretty much like C header files.Thanks.. but this is awkward. I expected there to be keywords to declare type declarations public or private.The keywords are "public" and "private".
Jul 08 2014
On Tuesday, 8 July 2014 at 10:47:26 UTC, NoUseForAName wrote:Also side question. What are these .di files? D propaganda radio told me that D does not need header files because it has a real module system (like e.g. Pascal or Go) yet in the solution Ali posted these .di files seem to be.. pretty much like C header files.They are optional, for those situations when you don't want to distribute the entire source code (e.g. proprietary library distributed in binary form). They are usually auto-generated by the compiler (dmd -H), and I agree that it's awkward to have to define them manually.So I could just put.. public struct S; private struct S { int i; } .. in the .d file and that would work? I mean I expected something like this but then why would Ali post such a complex solution?I guess because it's a (the only?) way to get real incomplete types. It is the most "literal" translation of what you described. But of course, there are better ways to achieve what you actually want. Your example above doesn't work, because it would be interpreted as a redefinition of the struct. Instead, you can use a public alias to a private type: // my_module.d: private struct MyStructImpl { int x; } public alias MyStructPtr = MyStructImpl*; void doSomething(MyStructPtr foo) { ... } // my_main_program.d: MyStructPtr bar; // OK MyStructImpl foo; // Error: my_module.MyStructImpl is private
Jul 08 2014
Marc Schütz:Instead, you can use a public alias to a private type: // my_module.d: private struct MyStructImpl { int x; } public alias MyStructPtr = MyStructImpl*; void doSomething(MyStructPtr foo) { ... } // my_main_program.d: MyStructPtr bar; // OK MyStructImpl foo; // Error: my_module.MyStructImpl is privateI still don't understand the point of doing this. Is disable this usable here? Bye, bearophile
Jul 08 2014
On Tuesday, 8 July 2014 at 11:16:52 UTC, Marc Schütz wrote:Your example above doesn't work, because it would be interpreted as a redefinition of the struct. Instead, you can use a public alias to a private type: // my_module.d: private struct MyStructImpl { int x; } public alias MyStructPtr = MyStructImpl*; void doSomething(MyStructPtr foo) { ... } // my_main_program.d: MyStructPtr bar; // OK MyStructImpl foo; // Error: my_module.MyStructImpl is privateThanks, that is what I was looking for.
Jul 08 2014
NoUseForAName:Thanks, that is what I was looking for.Why do you need a public pointer type but private struct type? Bye, bearophile
Jul 08 2014
On Tuesday, 8 July 2014 at 11:55:01 UTC, bearophile wrote:NoUseForAName:As the OP wrote:Thanks, that is what I was looking for.Why do you need a public pointer type but private struct type?In C my favorite way of achieving encapsulation is to use incomplete types.(Also known as PIMPL.) In C, it's the only type-safe way to get encapsulation, AFAIK. In languages with access protection, it's probably not as useful, but I'm sure it has its applications...
Jul 08 2014
On Tuesday, 8 July 2014 at 11:42:54 UTC, NoUseForAName wrote:On Tuesday, 8 July 2014 at 11:16:52 UTC, Marc Schütz wrote:Addendum: You also need to protect the members of MyStructImpl, like so: private struct MyStructImpl { private: // or `package:` int x; } Otherwise, they would still be accessible via dereferencing. (Don't worry, you _can_ access private members inside the module the struct is declared in, as access protection in D only applies across module boundaries.)Your example above doesn't work, because it would be interpreted as a redefinition of the struct. Instead, you can use a public alias to a private type: // my_module.d: private struct MyStructImpl { int x; } public alias MyStructPtr = MyStructImpl*; void doSomething(MyStructPtr foo) { ... } // my_main_program.d: MyStructPtr bar; // OK MyStructImpl foo; // Error: my_module.MyStructImpl is privateThanks, that is what I was looking for.
Jul 08 2014
On Tuesday, 8 July 2014 at 12:04:40 UTC, Marc Schütz wrote:Addendum: You also need to protect the members of MyStructImpl, like so: private struct MyStructImpl { private: // or `package:` int x; } Otherwise, they would still be accessible via dereferencing.Thanks again.
Jul 08 2014
Ali Çehreli:1) Put the opaque type and its functions into a .di file:[...] It seems your answer has scared NoUseForAName off. Next times we need to be more careful, and suggest a D-idiomatic solution instead. Bye, bearophile
Jul 08 2014
On 07/08/2014 03:35 AM, bearophile wrote:Ali Çehreli:I should have first asked what the need was. Ali1) Put the opaque type and its functions into a .di file:[...] It seems your answer has scared NoUseForAName off. Next times we need to be more careful, and suggest a D-idiomatic solution instead. Bye, bearophile
Jul 08 2014
NoUseForAName:In C my favorite way of achieving encapsulation is to use incomplete types. The module header contains the definition of an incomplete type and the prototypes for the public functions which operate on it.Probably in D you can archive something similar with different means. Bye, bearophile
Jul 07 2014