简体   繁体   中英

Initializing N std::unique_ptr with custom deleter in a template function

I need to map peripheral memory addresses to access the hardware in linux. To make things a bit more generic (aka complicated...) I created a following function:

template<typename Tp>
static Tp* getPeripheralPtr(unsigned address)
{
    static constexpr auto deleter = [](Tp* ptr){ munmap(ptr, sizeof(Tp); };
    static std::unique_ptr<Tp> ptr(nullptr, deleter);

    if (!ptr)
    {
        /* mmap logic */
        ptr.reset(reinterpret_cast<Tp*>(virtaddr));
    }

    return ptr.get();
}

where Tp is a structure representing the registers.

This worked pretty well, although later in the process, I realized I can have multiple controllers, for example PWM0, PWM1 with the same register layout, just with an offset. So I rewrote the function:

template<typename Tp, size_t nControllers = 1, size_t offset = 0>
static Tp* getPeripheralPtr(unsigned address, int idx = 0)
{
    static Storage<Tp, nControllers> storage;

    if (!storage.ptr[idx])
    {
        /* mmap magic */
    }

    return storage.ptr[idx].get();
}

I needed a way to initialize N std::unique_ptr instances so I created a helper Storage class:

template<typename Tp, std::size_t N>
class Storage
{
    static constexpr auto deleter = [](Tp* ptr) { munmap(ptr, sizeof(Tp)); };

    template<size_t ... indices>
    explicit Storage(std::index_sequence<indices...> const&)
        : ptr{{((void)indices, ptr_type(nullptr, deleter))...}}
    {
    }
public:
    using ptr_type = std::unique_ptr<Tp, decltype(deleter)>;
    ptr_type ptr[N];

    Storage() : Storage(std::make_index_sequence<N>{}) {}
};

But it gives me an error when nControllers > 1 about no matching constructor for initialization of 'Storage<int, 2>::ptr_type'. Can you please point me in a right direction?

With this:

ptr{{((void)indices, ptr_type(nullptr, deleter))...}}

You need a type within an initializer_list constructor. And obviously, you couldn't use just a raw C-array. If you remove one braces level you could use it with raw C-array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM