On Monday, 29 May 2017 at 23:39:17 UTC, Russel Winder wrote:
C++ allows one to create types that are pointer types but wrap a primitive pointer to give RAII handling of resources. For example:


    class Dvb::FrontendParameters_Ptr {
    private:
            dvb_v5_fe_parms * ptr;
    public:
FrontendParameters_Ptr(FrontendId const & fei, unsigned int const verbose = 0, unsigned int const legacy = 0); FrontendParameters_Ptr(FrontendParameters_Ptr const &) = delete; FrontendParameters_Ptr & operator=(FrontendParameters_Ptr const &) = delete;
            ~FrontendParameters_Ptr() {dvb_fe_close(ptr); }
            dvb_v5_fe_parms * c_ptr() const { return ptr; }
            dvb_v5_fe_parms * operator->() const { return ptr; }
    };


Has anyone any experience of doing the analogous thing idiomatically in D.

I just re-realised I manually constructed a C++ abstraction layer around some of libdvbv5, so I am going to do the same for D. However whilst I (sort of) understand doing the wrapping with C++, I am not sure I have seen anyone wrapping C pointers with RAII in D.

I've found this pattern works rather well:

module frontendparametersptr;

struct FrontendParametersPtr
{
    // No constructors, initialization with parameters
    // is done via the frontendParametersPtr function
    @disable this(this);

    ~this()
    {
        // null check is often useful to detect e.g.
        // if this object has been `move`d
        if (_ptr) dvb_fe_close(_ptr);
    }

    // with DIP1000, could also return `scope`
    inout(dvb_v5_fe_parms)* ptr() inout { return _ptr; }
    alias ptr this;
package:

    void construct(/*your args here*/) { /*...*/ }

private:
    dvb_v5_fe_parms* _ptr;
}

/// Replaces constructor, i.e. can be called with no arguments for
/// replacing "default" construction of C++
auto frontendParametersPtr(Args...)(auto ref Args args)
{
    import std.functional : forward;
    FrontendParametersPtr result = void;
    result.construct(forward!args);
    return result; // moves result, no copy is made
}

///-----

module app;

import frontendparametersptr;

void main()
{
    auto ptr = frontendParametersPtr(/* your args here */);
}


The main idea is that construction is handled by the `construct` function (which could be overloaded), instead of `this(...)` constructors: this way client code would either get default-initialized (.init) pointers, or those constructed with appropriate arguments (even with no arguments, if such is needed).
Disabling copying is obvious.
The rest depends on taste and purpose.
  • Re: RAII pointers Stanislav Blinov via Digitalmars-d-learn

Reply via email to