Jump to page: 1 2
Thread overview
How to create friends of a class at compile time?
Jul 15, 2021
Tejas
Jul 15, 2021
Adam D Ruppe
Jul 15, 2021
Tejas
Jul 15, 2021
Tejas
Jul 16, 2021
Ali Çehreli
Jul 16, 2021
Ali Çehreli
Jul 15, 2021
jfondren
Jul 15, 2021
Tejas
Jul 15, 2021
evilrat
Jul 15, 2021
Tejas
Jul 15, 2021
H. S. Teoh
Jul 15, 2021
Tejas
July 15, 2021

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.

July 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.

July 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:

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:

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

July 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.
July 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 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.

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?

July 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.


July 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 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:

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:

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

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.

July 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

July 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.

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
}
July 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:

>

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.

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
}

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!

« First   ‹ Prev
1 2