Safely wrapping an uncopyable struct to implement an interface

aliak something at something.com
Wed Mar 4 14:04:39 UTC 2020


On Wednesday, 4 March 2020 at 12:03:48 UTC, Gregor Mückl wrote:
> Hi!
>
> I've just created a situation in my code that is summarized by 
> the following example. I don't know how to solve it with @safe 
> code.
>
> A third party library provides a struct that is not copyable:
>
> // provided by third party
> struct Foo {
>     @disable this() @safe;
>     @disable this(ref return scope Foo other) @safe;
>
>     void magic() @safe;
> }
>
> What I want to do is to provide a safe wrapper around it that 
> adapts to another interface:
>
> // intended common interface
> interface IWrapper {
>     void bar() @safe;
> }
>
> Now, the obvious way to wrap this fails:
>
> class FooWrapper : IWrapper {
>     Foo f;
>
>     this(Foo f) @safe {
>         this.f = f; // this fails because it would be a copy
>     }
>
>     override void bar() @safe
>     {
>         f.magic();
>     }
> }
>
> If Foo were a class, f would be a reference and everything 
> would be fine. But f is a struct that can't be copied and 
> taking a pointer to f makes FooWrapper obviously unsafe. How 
> could I solve this?
>
> I've come up with a workaround for my actual use case that 
> doesn't need to use the uncopyable struct this way. But I'm 
> curious if I'm missing something regarding references to 
> structs.

You can use move maybe? : 
https://dlang.org/library/std/algorithm/mutation/move.html

So

this.f = f.move;

But you should be aware that it could cause problems when f has 
pointers to its internals. I.e. if Foo had a pointer to it's own 
member then the value of of that pointer to me "copied" over to 
this.f, but the address of the member in this.f is different that 
the original f's member address.





More information about the Digitalmars-d-learn mailing list