Thread overview
friends with phobos, workaround?
Sep 09, 2015
Daniel N
Sep 09, 2015
Idan Arye
Sep 10, 2015
Daniel N
Sep 10, 2015
Daniel N
Sep 10, 2015
Adam D. Ruppe
Sep 11, 2015
Daniel N
Sep 10, 2015
Adam D. Ruppe
September 09, 2015
For the record, I think D made the right decision... omitting friends.

However there's one case in particular which I find useful, anyone see a good workaround for this?

#include <memory>

class Friendly
{
private:
  int val;
  Friendly(int&& val) : val(val) {}
  friend std::unique_ptr<Friendly> std::make_unique<Friendly>(int&& val);
};

int main()
{
  auto yay = std::make_unique<Friendly>(1);
  auto nay = new Friendly(1);
}

September 09, 2015
On Wednesday, 9 September 2015 at 20:19:44 UTC, Daniel N wrote:
> For the record, I think D made the right decision... omitting friends.
>
> However there's one case in particular which I find useful, anyone see a good workaround for this?
>
> #include <memory>
>
> class Friendly
> {
> private:
>   int val;
>   Friendly(int&& val) : val(val) {}
>   friend std::unique_ptr<Friendly> std::make_unique<Friendly>(int&& val);
> };
>
> int main()
> {
>   auto yay = std::make_unique<Friendly>(1);
>   auto nay = new Friendly(1);
> }

How about using a mixin template(http://dlang.org/template-mixin.html)?




module makeunique;

mixin template MakeUnique(Args...)
{
    import std.typecons : Unique;

    static Unique!(typeof(this)) makeUnique(Args args)
    {
        return Unique!Friendly(new typeof(this)(args));
    }
}




module friendly;

import makeunique;

struct Friendly
{
private:
    int val;
    this(int val)
    {
        this.val = val;
    }

public:
    mixin MakeUnique!(int);
};





module app;

import std.stdio;
import std.typecons;

import friendly;

void main()
{
    auto yay = Friendly.makeUnique(1);
}

September 10, 2015
On Wednesday, 9 September 2015 at 23:44:14 UTC, Idan Arye wrote:
> How about using a mixin template(http://dlang.org/template-mixin.html)?
>

Thanks, it's a good solution. My only reservation is I would prefer to find a way to directly invoke a symbol in std.* as otherwise different frameworks might invent their own conventions(well they might do that anyway). After a nights sleep, I actually found such a solution!

This opens the door to a new class of meta-programming; introspect the caller! :)

import std.typecons;

class Awesome1
{
private:
  int val;
  this(string caller = __MODULE__)(int val) if(caller == "std.conv") // Use scoped!Awesome
  {
  	this.val = val;
  }
}

class Awesome2
{
private:
  int val;
  this(string caller = __MODULE__)(int val)
  {
  	static assert(caller == "std.conv", "Use scoped!Awesome(...)!");

  	this.val = val;
  }
}

void main()
{
  static assert(__traits(compiles, scoped!Awesome1(1)));
  static assert(__traits(compiles, scoped!Awesome2(1)));
  static assert(!__traits(compiles, new Awesome1(1)));
  static assert(!__traits(compiles, new Awesome2(1)));
}



September 10, 2015
On Thursday, 10 September 2015 at 08:22:29 UTC, Daniel N wrote:
> import std.typecons;
>
> class Awesome1
> {
> private:
>   int val;
>   this(string caller = __MODULE__)(int val) if(caller == "std.conv") // Use scoped!Awesome
>   {
>   	this.val = val;
>   }
> }
>
> class Awesome2
> {
> private:
>   int val;
>   this(string caller = __MODULE__)(int val)
>   {
>   	static assert(caller == "std.conv", "Use scoped!Awesome(...)!");
>
>   	this.val = val;
>   }
> }
>
> void main()
> {
>   static assert(__traits(compiles, scoped!Awesome1(1)));
>   static assert(__traits(compiles, scoped!Awesome2(1)));
>   static assert(!__traits(compiles, new Awesome1(1)));
>   static assert(!__traits(compiles, new Awesome2(1)));
> }

PS 'private:' should of course be 'public:' when using this idiom.

September 10, 2015
On Wednesday, 9 September 2015 at 23:44:14 UTC, Idan Arye wrote:
> public:
>     mixin MakeUnique!(int);


I actually think that should be a free function in the module because then it can be used by derived classes too without having to mix it in each of them as well.
September 10, 2015
On Thursday, 10 September 2015 at 08:22:29 UTC, Daniel N wrote:
>   this(string caller = __MODULE__)(int val) if(caller == "std.conv") // Use scoped!Awesome

That's disgustingly.... genius. I'm a bit jealous I didn't think of it myself!

One slight problem though: you couldn't call super() from a derived class, since the constructor wouldn't even exist due to the constraint.

You could just put the hard work in a protected helper function though and then child classes call it instead of the super ctor....
then you could do a mixin template that forwards to that to kinda automate this ctor too.

this is fairly usable!
September 11, 2015
On Thursday, 10 September 2015 at 13:19:08 UTC, Adam D. Ruppe wrote:
> On Thursday, 10 September 2015 at 08:22:29 UTC, Daniel N wrote:
>>   this(string caller = __MODULE__)(int val) if(caller == "std.conv") // Use scoped!Awesome
>
> That's disgustingly.... genius. I'm a bit jealous I didn't think of it myself!
>
> One slight problem though: you couldn't call super() from a derived class, since the constructor wouldn't even exist due to the constraint.
>

super():
Hmm, yes that's a slight nuisance but manageable.

Thanks, coming from you that means a lot. :) Hmm, maybe I'll wait a week or two before I share my next trick to give you ample time to think of it also, meanwhile I'll just scribble it down in the margin of my copy of "D Cookbook". ;) ... just hope I didn't jinx myself now ...