September 20, 2021

I have made an owner type that wraps malloc'd pointers with custom destroy functions from a C library and utilizes RefCounted for safety. I would like to be able to use the owner type Memory implicitly as its underlying pointer type via alias this.

struct Memory(T, alias destroy)
if(!isPointer!T && isSomeFunction!destroy)
{
    @safe:
    /// Pointer Wrapper
    struct Ptr
    {
        /// data pointer
        T * ptr;

        /// no copying this as that could result
        /// in premature destruction
        @disable this(this);

        /// destroy
        ~this() @trusted
        {
            /// if destroy function return is void
            /// just destroy
            /// else if int
            /// destroy then check return value
            /// else don't compile
            static if(is(ReturnType!destroy == void))
                destroy(this.ptr);
            else static if(is(ReturnType!destroy == int))
            {
                auto success = destroy(this.ptr);
                if(!success) hts_log_error(__FUNCTION__,"Couldn't destroy "~T.stringof~" * data using function "~destroy.stringof);
            }else{
                static assert(0, "Memory doesn't recognize destroy function return type");
            }
        }
    }

    /// reference counted Ptr
    RefCounted!(Ptr, RefCountedAutoInitialize.yes) rcPtr;

    /// get underlying data pointer
    /// copied from RefCounted implementation
    @property nothrow pure @nogc
    ref inout(T*) getPtr() inout return
    {
        return rcPtr.refCountedPayload.ptr;
    }

    /// allow Memory to be used as
    /// underlying ptr type
    alias getPtr this;

    /// ctor from raw pointer
    this(T * rawPtr) @trusted
    {
        auto wrapped = Ptr(rawPtr);
        move(wrapped,this.rcPtr.refCountedPayload);
    }
}

With alias this I can use auto rc = Memory!(ctype, ctype_destroy)(ctype_init()); (where ctype_destroy and ctype_init are C bindings) and then ctype * ptr = rc;. This is great since I can pass rc directly to c functions that accept ctype *. But how do I either: ensure rc stays in scope or have compile-time protection against escaping ptr past the lifetime of rc. Is this possible with either scope or @live? Could I add attributes to the C bindings to help with this?

September 23, 2021

Yes, the return attribute is what should do it. You also need to compile the code with -dip1000 option.