Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
291 views
in Technique[技术] by (71.8m points)

c++ - How do I initialize a std::unique_ptr with a deleter in a constructor?

I'm trying to wrap a C library raw pointer in a std::unique_ptr and use the constructor with the Deleter to call the library free function. I have to do some setup in the constructor in order to setup the raw pointer so I can't construct the unique_ptr in the initializer list.

.h

class Resampler {

public:
    Resampler(unsigned int baseSamplerate, unsigned int channels);
  
private:
    std::unique_ptr<SwrContext, decltype(&swr_free)> context{nullptr, nullptr};
};

.cpp

Resampler::Resampler(unsigned int baseSamplerate, unsigned int channels) : baseSamplerate(baseSamplerate), ratio(1.0), channels(channels) {

    int64_t channelLayout;
     ..

    SwrContext *ctx = swr_alloc_set_opts(nullptr,
                                         channelLayout,
                                         AV_SAMPLE_FMT_FLTP,
                                         baseSamplerate,
                                         channelLayout,
                                         AV_SAMPLE_FMT_FLTP,
                                         baseSamplerate,
                                         0,
                                         nullptr);

    context = std::unique_ptr<SwrContext, decltype(&swr_free)>(ctx, &swr_free);
    setRatio(1.0);
}

This doesn't produce an error in the IDE but the compiler complains:

> error: cannot initialize a parameter of type 'SwrContext **' with an
> lvalue of type 'std::__ndk1::unique_ptr<SwrContext, void
> (*)(SwrContext **)>::pointer' (aka 'SwrContext *')
std::unique_ptr<SwrContext, decltype(&swr_free)> context{ nullptr };

and

std::unique_ptr<SwrContext, decltype(&swr_free)> context{};

are not valid constructors, and

std::unique_ptr<SwrContext, decltype(&swr_free)> context;

produces

error: constructor for 'Resampler' must explicitly initialize the member 'context' which does not have a default constructor

so is there a way to do this or should I just make context a raw pointer and manually manage?

question from:https://stackoverflow.com/questions/66056463/how-do-i-initialize-a-stdunique-ptr-with-a-deleter-in-a-constructor

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The deleter of a std::unique_ptr<T> has to be a callable object in this case. Try using a functor like this:

struct swr_deleter
{
    void operator()(SwrContext* context)
    {
        if (context != nullptr)
        {
            swr_free(context);
        }
    }
}

Then your std::unique_ptr will look like this:

std::unique_ptr<SwrContext, swr_deleter> context;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...