我正在开发一个程序(仿真器),在该程序中我需要访问仿真机的内存映射。使用模板函数(已读)完成。
此函数根据模板参数返回数据大小(即 read
这是通过3个指向函数的指针数组( read_8_handler _ , read_16_handler _ , read_32_handler _ )完成的,将每个地址链接到特定函数。
这些数组的初始化针对每个链接的函数调用3次initializeHandlers来完成:
// default handlers
initializeHandler<uint8_t>(0x00, 0xFF, readDummy<uint8_t>);
initializeHandler<uint16_t>(0x00, 0xFF, readDummy<uint16_t>);
initializeHandler<uint32_t>(0x00, 0xFF, readDummy<uint32_t>);
// rom handlers
initializeHandler<uint8_t>(0x60, 0x6F, readRom<uint8_t>);
initializeHandler<uint16_t>(0x60, 0x6F, readRom<uint16_t>);
initializeHandler<uint32_t>(0x60, 0x6F, readRom<uint32_t>);
这导致大量的冗余,因为每个处理程序必须使用3行进行初始化。
所以我的问题是:我可以使用一个内衬来初始化一个处理程序,而不提供像这样的模板参数:
initializeHandler(0x00, 0xFF, readDummy);
initializeHandler(0x60, 0x6F, readRom);
? 我认为可以使用模板模板参数来完成此操作,但是我对模板的流利程度不足以找出如何做到这一点...
这是完整的示例,可以通过here进行测试
#include <iostream>
#include <cstdlib>
#include <array>
#include <tuple>
template <typename R, typename ...ARGS> using function = R(*)(ARGS...);
template<typename T> using ReadType = function<T, const uint32_t>;
template<class ReadType> using ReadHandlerType = std::array<ReadType, 0x100>;
template<typename T> using ReadHandler = ReadHandlerType<ReadType<T>>;
ReadHandler<uint8_t> read_8_handler_;
ReadHandler<uint16_t> read_16_handler_;
ReadHandler<uint32_t> read_32_handler_;
template<typename T>
T readDummy( const uint32_t addr) {
return sizeof(T{});
}
template<typename T>
T readRom( const uint32_t addr) {
return sizeof(T{})*2;
}
template<typename T>
void initializeHandler(uint32_t begin,
uint32_t end,
ReadType<T> func) {
auto t = std::tie(read_8_handler_, read_16_handler_, read_32_handler_);
for (uint32_t current = begin; current <= end; ++current) {
auto& handler = std::get < ReadHandler<T>& >(t);
handler[current & 0xFF] = func;
}
}
template<typename T>
T read(const uint32_t addr) {
auto& handler = std::get < ReadHandler<T>& >(std::tie(read_8_handler_, read_16_handler_, read_32_handler_));
return handler[addr](addr);
}
int main()
{
initializeHandler<uint8_t>(0x00, 0xFF, readDummy<uint8_t>);
initializeHandler<uint16_t>(0x00, 0xFF, readDummy<uint16_t>);
initializeHandler<uint32_t>(0x00, 0xFF, readDummy<uint32_t>);
initializeHandler<uint8_t>(0x60, 0x6F, readRom<uint8_t>);
initializeHandler<uint16_t>(0x60, 0x6F, readRom<uint16_t>);
initializeHandler<uint32_t>(0x60, 0x6F, readRom<uint32_t>);
std::cout << read<uint16_t>( 0x20) << std::endl;
std::cout << read<uint16_t>( 0x60) << std::endl;
}
答案 0 :(得分:1)
您可以将readDummy
和readRom
转换为可转换为ReadType<T>
的类型,并使用以下折叠表达式:
template<typename T>
struct readDummy
{
operator ReadType<T>() const {
return [] (const uint32_t addr) -> T {
return sizeof(T{});
};
}
};
template<typename T>
struct readRom
{
operator ReadType<T>() const {
return [] (const uint32_t addr) -> T {
return sizeof(T{})*2;
};
}
};
template <template <class> class ReadType, class... T>
auto initialize(uint32_t begin, uint32_t end)
{
(initializeHandler<T>(begin, end, ReadType<T>{}), ...);
}
initialize<readDummy, uint8_t, uint16_t, uint32_t>(0x00, 0x0FF);
initialize<readRom, uint8_t, uint16_t, uint32_t>(0x60, 0xFF);