Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
September 09, 2015 friends with phobos, workaround? | ||||
---|---|---|---|---|
| ||||
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 Re: friends with phobos, workaround? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel N | 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 Re: friends with phobos, workaround? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | 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 Re: friends with phobos, workaround? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel N | 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 Re: friends with phobos, workaround? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | 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 Re: friends with phobos, workaround? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel N | 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 Re: friends with phobos, workaround? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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 ...
|
Copyright © 1999-2021 by the D Language Foundation