在模板函数中使用自定义删除器初始化 N std::unique_ptr
Initializing N std::unique_ptr with custom deleter in a template function
我需要映射外设内存地址以访问 linux 中的硬件。为了使事情更通用(又名复杂......)我创建了以下函数:
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();
}
其中 Tp 是表示寄存器的结构。
这工作得很好,虽然在这个过程的后期,我意识到我可以有多个控制器,例如 PWM0、PWM1,它们具有相同的寄存器布局,只是有一个偏移量。所以我重写了函数:
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();
}
我需要一种方法来初始化 N std::unique_ptr 个实例,所以我创建了一个辅助存储 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>{}) {}
};
但是当 nControllers > 1 时,它会给我一个错误,关于 'Storage<int, 2>::ptr_type' 的初始化没有匹配的构造函数。你能给我指明正确的方向吗?
有了这个:
ptr{{((void)indices, ptr_type(nullptr, deleter))...}}
您需要 initializer_list
构造函数中的类型。显然,您不能只使用原始 C 数组。如果删除一个大括号级别,则可以将其与原始 C 数组一起使用。
我需要映射外设内存地址以访问 linux 中的硬件。为了使事情更通用(又名复杂......)我创建了以下函数:
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();
}
其中 Tp 是表示寄存器的结构。
这工作得很好,虽然在这个过程的后期,我意识到我可以有多个控制器,例如 PWM0、PWM1,它们具有相同的寄存器布局,只是有一个偏移量。所以我重写了函数:
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();
}
我需要一种方法来初始化 N std::unique_ptr 个实例,所以我创建了一个辅助存储 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>{}) {}
};
但是当 nControllers > 1 时,它会给我一个错误,关于 'Storage<int, 2>::ptr_type' 的初始化没有匹配的构造函数。你能给我指明正确的方向吗?
有了这个:
ptr{{((void)indices, ptr_type(nullptr, deleter))...}}
您需要 initializer_list
构造函数中的类型。显然,您不能只使用原始 C 数组。如果删除一个大括号级别,则可以将其与原始 C 数组一起使用。