www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - friends with phobos, workaround?

reply "Daniel N" <ufo orbiting.us> writes:
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);
}
Sep 09 2015
parent reply "Idan Arye" <GenericNPC gmail.com> writes:
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); }
Sep 09 2015
next sibling parent reply "Daniel N" <ufo orbiting.us> writes:
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))); }
Sep 10 2015
next sibling parent "Daniel N" <ufo orbiting.us> writes:
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.
Sep 10 2015
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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!
Sep 10 2015
parent "Daniel N" <ufo orbiting.us> writes:
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 ...
Sep 11 2015
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Sep 10 2015