digitalmars.D.learn - How to create friends of a class at compile time?
- Tejas (9/9) Jul 15 2021 I can do it like this in C++:
- Adam D Ruppe (3/4) Jul 15 2021 You don't just put class def and class abc in the same module and
- Tejas (54/58) Jul 15 2021 I really should've just posted the whole thing...
- Steven Schveighoffer (8/11) Jul 15 2021 Functions in the same module can access `private` members. Functions in
- Tejas (12/26) Jul 15 2021 Yes, it seems like seperating chunks of C++ code into seperate
- =?UTF-8?Q?Ali_=c3=87ehreli?= (19/25) Jul 15 2021 That would be necessary if one agreed with C++'s 'private' to begin
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/8) Jul 15 2021 Ok, I said all that before realizing what you needed with transpiling=20
- jfondren (26/35) Jul 15 2021 Uncharitably: D is a friendless language. Charitably: D is so
- Tejas (6/42) Jul 15 2021 I'm sorry, I should've explicitly mentioned I'm interested in
- H. S. Teoh (12/22) Jul 15 2021 D does not have `friend` declarations. Equivalent functionality is
- Tejas (5/10) Jul 15 2021 Was just dreaming of how to transpile C++ code to D :(
I can do it like this in C++: ``` template<class abc> class def { friend typename abc; } ``` I am just hopelessly confused on how to achieve the same in D.
Jul 15 2021
On Thursday, 15 July 2021 at 17:21:45 UTC, Tejas wrote:I can do it like this in C++:You don't just put class def and class abc in the same module and you get the same effect though.
Jul 15 2021
On Thursday, 15 July 2021 at 17:26:41 UTC, Adam D Ruppe wrote:On Thursday, 15 July 2021 at 17:21:45 UTC, Tejas wrote:I really should've just posted the whole thing... I know how modules and access specifiers work in D I was just reading the source of one of the files of libcxx and came across this: ``` template <class _Cp, bool = __has_storage_type<_Cp>::value> class __bit_reference { typedef typename _Cp::__storage_type __storage_type; typedef typename _Cp::__storage_pointer __storage_pointer; __storage_pointer __seg_; __storage_type __mask_; //PART I'M CONCERNED WITH *********************************** friend typename _Cp::__self; friend class __bit_const_reference<_Cp>; friend class __bit_iterator<_Cp, false>; //END OF PART I'M CONCERNED WITH ************************ public: _LIBCPP_INLINE_VISIBILITY __bit_reference(const __bit_reference&) = default; _LIBCPP_INLINE_VISIBILITY operator bool() const _NOEXCEPT {return static_cast<bool>(*__seg_ & __mask_);} _LIBCPP_INLINE_VISIBILITY bool operator ~() const _NOEXCEPT {return !static_cast<bool>(*this);} _LIBCPP_INLINE_VISIBILITY __bit_reference& operator=(bool __x) _NOEXCEPT { if (__x) *__seg_ |= __mask_; else *__seg_ &= ~__mask_; return *this; } _LIBCPP_INLINE_VISIBILITY __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT {return operator=(static_cast<bool>(__x));} _LIBCPP_INLINE_VISIBILITY void flip() _NOEXCEPT {*__seg_ ^= __mask_;} _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, false> operator&() const _NOEXCEPT {return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(__libcpp_ctz(__mask_)));} private: _LIBCPP_INLINE_VISIBILITY __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT : __seg_(__s), __mask_(__m) {} }; ``` How do you write the equivalent of that in D? Is the answer still the same? Manually keep it in the same module, or is there a programmatic way of converting this to D?I can do it like this in C++:You don't just put class def and class abc in the same module and you get the same effect though.
Jul 15 2021
On 7/15/21 1:43 PM, Tejas wrote:How do you write the equivalent of that in D? Is the answer still the same? Manually keep it in the same module, or is there a programmatic way of converting this to D?Functions in the same module can access `private` members. Functions in the same package (or in whatever package you specify) can access `package` members. That is how D does "friends". So the answer to your question depends on how the C++ code is organized. It's always possible that something in C++ here is not translatable into D, but most likely can be redesigned (and likely better designed). -Steve
Jul 15 2021
On Thursday, 15 July 2021 at 18:06:26 UTC, Steven Schveighoffer wrote:On 7/15/21 1:43 PM, Tejas wrote:Yes, it seems like seperating chunks of C++ code into seperate modules and using the ```d package(qualifiedIdentifier) ``` access specifier seems to be the way to go. Was wondering if there was some wizardry that the veterans knew that would make it less difficult, but it seems this is the only way. Thank you very much for replying!How do you write the equivalent of that in D? Is the answer still the same? Manually keep it in the same module, or is there a programmatic way of converting this to D?Functions in the same module can access `private` members. Functions in the same package (or in whatever package you specify) can access `package` members. That is how D does "friends". So the answer to your question depends on how the C++ code is organized. It's always possible that something in C++ here is not translatable into D, but most likely can be redesigned (and likely better designed). -Steve
Jul 15 2021
On 7/15/21 11:24 AM, Tejas wrote:it seems like seperating chunks of C++ code into seperate modules and using the ```d package(qualifiedIdentifier) ``` access specifier seems to be the way to go.That would be necessary if one agreed with C++'s 'private' to begin with. In other words, one would agree that implementations inside one source file should be protected from each other. Through Walter Bright's experience, D does not buy into that view: It is silly to protect implementation details of features of the same file from each other. Personally, I fully agree! I am rarely strongly opinionated; this topic is one of those cases. :) In hind sight, this is one of the examples of D that thought me and improved me. C++'s 'friend' "feature" covers up a language design mistake: It is a mistake because a tool should be useful; C++'s 'private' protects the programmer unnecessarily strongly from himself or herself. What a view that causes unnecessary mental load on many programmers with the 'friend' keyword... If you agree with all of that, then your idea of separating chunks into separate modules becomes unnecessary work. Just don't do it and you will miss nothing at all. You will gain a lot in the future without even noticing it. :) Ali
Jul 15 2021
On 7/15/21 5:46 PM, Ali =C3=87ehreli wrote:On 7/15/21 11:24 AM, Tejas wrote:> package(qualifiedIdentifier)Just don't do itOk, I said all that before realizing what you needed with transpiling=20 C++ to D and the solution of package(qualifiedIdentifier). (And=20 package(qualifiedIdentifier) is news to me! :) ) Ali
Jul 15 2021
On Thursday, 15 July 2021 at 17:21:45 UTC, Tejas wrote:I can do it like this in C++: ``` template<class abc> class def { friend typename abc; } ``` I am just hopelessly confused on how to achieve the same in D.Uncharitably: D is a friendless language. Charitably: D is so much more friendly that instead of a short explicit list of friends, D has a large implicit list of friends: everything else in a module. That's why this works: ```d class Secret { private int id; } void main() { import std.stdio : writeln; auto s = new Secret; writeln("visible to me: ", s.id); } ``` But this doesn't: ```d void main() { import std.stdio : writeln; import secret : Secret; auto s = new Secret; writeln("visible to me: ", s.id); } ``` Error: no property `id` for type `secret.Secret`
Jul 15 2021
On Thursday, 15 July 2021 at 17:30:05 UTC, jfondren wrote:On Thursday, 15 July 2021 at 17:21:45 UTC, Tejas wrote:I'm sorry, I should've explicitly mentioned I'm interested in learning how to do friend injection in D. I know that access specifiers operate at module scope, seen a few posts about that here already. Thank you for answering though.I can do it like this in C++: ``` template<class abc> class def { friend typename abc; } ``` I am just hopelessly confused on how to achieve the same in D.Uncharitably: D is a friendless language. Charitably: D is so much more friendly that instead of a short explicit list of friends, D has a large implicit list of friends: everything else in a module. That's why this works: ```d class Secret { private int id; } void main() { import std.stdio : writeln; auto s = new Secret; writeln("visible to me: ", s.id); } ``` But this doesn't: ```d void main() { import std.stdio : writeln; import secret : Secret; auto s = new Secret; writeln("visible to me: ", s.id); } ``` Error: no property `id` for type `secret.Secret`
Jul 15 2021
On Thursday, 15 July 2021 at 17:49:06 UTC, Tejas wrote:I'm sorry, I should've explicitly mentioned I'm interested in learning how to do friend injection in D. I know that access specifiers operate at module scope, seen a few posts about that here already. Thank you for answering though.Probably the only way is CRTP (unlikely) or mixin that access internals. Both will be limited and cumbersome to use though. Additionally there is "package" visibility kind that takes optional package name to give access to specific package. https://dlang.org/spec/grammar.html#attributes (under visibility attributes) I rarely use package visibility so might be incorrect, but here an example anyway. ```d module somepackage.somemod; struct A { private int x; // only accessible from same module package int y; // accessible from any module in 'somepackage' package(otherpackage) int z; // accessible from 'otherpackage' package } ```
Jul 15 2021
On Thursday, 15 July 2021 at 18:11:30 UTC, evilrat wrote:On Thursday, 15 July 2021 at 17:49:06 UTC, Tejas wrote:CRTP and mixins are our best solution against multiple inheritance. Doubt they'll help with friend injection. I also could only think of package specifiers for access control, but wondered whether it could be drilled down to a specific module, rather than package level. you think ``` package(otherpackage.specific_module)``` is valid D code? Thanks for replying, much appreciated!I'm sorry, I should've explicitly mentioned I'm interested in learning how to do friend injection in D. I know that access specifiers operate at module scope, seen a few posts about that here already. Thank you for answering though.Probably the only way is CRTP (unlikely) or mixin that access internals. Both will be limited and cumbersome to use though. Additionally there is "package" visibility kind that takes optional package name to give access to specific package. https://dlang.org/spec/grammar.html#attributes (under visibility attributes) I rarely use package visibility so might be incorrect, but here an example anyway. ```d module somepackage.somemod; struct A { private int x; // only accessible from same module package int y; // accessible from any module in 'somepackage' package(otherpackage) int z; // accessible from 'otherpackage' package } ```
Jul 15 2021
On Thu, Jul 15, 2021 at 05:21:45PM +0000, Tejas via Digitalmars-d-learn wrote:I can do it like this in C++: ``` template<class abc> class def { friend typename abc; } ``` I am just hopelessly confused on how to achieve the same in D.D does not have `friend` declarations. Equivalent functionality is achieved by `private` being module-private rather than aggregate-private, meaning that all you have to do is to put `abc` in the same module as `def`, and it will have access to all `def`s private members. If, however, you're trying to inject friend access to something outside def's module, then you might want to reconsider what you're trying to accomplish and whether it can be done differently. T -- Obviously, some things aren't very obvious.
Jul 15 2021
If, however, you're trying to inject friend access to something outside def's module, then you might want to reconsider what you're trying to accomplish and whether it can be done differently.Was just dreaming of how to transpile C++ code to D :( Curiously enough, friend injection was not made part of the standard back in 1998 and only g++ supported it through a non-standard extension. But now here we are. I wonder why this was allowed.
Jul 15 2021