如何一次调用多个模板化函数?

时间:2018-12-06 22:02:41

标签: c++11 templates c++14 c++17

我正在开发一个程序(仿真器),在该程序中我需要访问仿真机的内存映射。使用模板函数(已读)完成。
此函数根据模板参数返回数据大小(即 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;
}

1 个答案:

答案 0 :(得分:1)

您可以将readDummyreadRom转换为可转换为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);