【发布时间】:2018-12-06 22:02:41
【问题描述】:
我正在开发一个程序(模拟器),我需要在其中访问模拟机器的内存映射。这是使用模板函数完成的(读取)。
此函数根据模板化参数返回数据大小(即read(0x10)将从内存地址0x10返回8位数据,read(0x20) 将从内存地址 0x20) 等返回 32 位数据。
这是使用 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;
}
【问题讨论】:
-
如果有的话,
initializeHandler(0x00, 0xFF, readDummy<uint8_t>);可以工作并且已经比你正在做的更好。 -
好电话,我没想到这个参数是从另一个参数推导出来的……谢谢你的信息!
标签: c++11 templates c++14 c++17