【问题标题】:Replace arrays of function pointers using templates in modern c++在现代 C++ 中使用模板替换函数指针数组
【发布时间】:2018-10-27 21:04:56
【问题描述】:

我有一些遗留代码使用函数指针数组来模拟内存处理程序。
所以我现在正在尝试使用模板来获得相同的功能。
到目前为止,这是我尝试过的:

template <typename R, typename ...ARGS> using function = R(*)(ARGS...);
template<size_t Size> using ReadType    = function<SizedUInt<Size>, const uint32_t>;

// arrays to redeclare
std::array<ReadType<8>,   memory_handler_size> read_8_handler_;
std::array<ReadType<16>,  memory_handler_size> read_16_handler_;
std::array<ReadType<32>,  memory_handler_size> read_32_handler_;

template<size_t Size>
void initializeReadHandler(uint32_t begin,
                           uint32_t end,
                           ReadType<Size> func) {
    begin >>= 16;
    end >>= 16;
    for (uint32_t current = begin; current <= end; ++current) {
         //read_handler_[current & 0xFFFF] = func;
    }
}

如何声明读取处理程序数组以便使用模板化的initializeReadHandler() 函数对其进行初始化?
我不想使用std::function,因为我负担不起性能开销...

...编辑...
这是基于 Yakk 的回答、max66 备注和一些小修复(错字等)的代码:

template <typename R, typename ...ARGS> using function = R(*)(ARGS...);
template<size_t S> using ReadType    = function<SizedUInt<S>, const uint32_t>;

template<class ReadType>
using ReadHandlerType = std::array<ReadType, memory_handler_size>;

ReadHandler<8> read_8_handler_;
ReadHandler<16> read_16_handler_;
ReadHandler<32> read_32_handler_;

template<size_t S>
void initializeReadHandler(uint32_t begin,
                           uint32_t end,
                           ReadType<S> func) {
    begin >>= 16;
    end >>= 16;

    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<S>& >(t);
        handler[current & 0xFFFF] = func;
    }
}

像魅力一样工作:D 谢谢大家!

【问题讨论】:

  • 这对我来说很好,你有什么特别的问题吗?
  • 其实我不知道如何在注释行中选择正确的数组...

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


【解决方案1】:

如果我理解正确并且您不想维护 read_8_handler_、read_16_handler_ 和 read_32_handler_ 全局变量(一种),我想您可以将它们包装为模板函数中的静态变量(按照 Quentin 的建议)

某事

 template <std::size_t S>
 std::array<ReadType<S>, memory_handler_size> & getHandler () 
   { static std::array<ReadType<S>, memory_handler_size> h; return h; }

所以你可以使用推导出来的Size模板参数来选择请求的函数

template<size_t Size>
void initializeReadHandler(uint32_t begin,
                           uint32_t end,
                           ReadType<Size> func) {
    begin >>= 16;
    end >>= 16;

    auto & handler = getHandler<Size>();

    for (uint32_t current = begin; current <= end; ++current) {
       handler[current & 0xFFFF] = func;
    }
}

但是,如果可能的话,我建议您将数组(通过引用)作为参数传递给函数。

【讨论】:

  • 为什么struct带有静态函数而不是免费函数模板?
  • @Quentin - 哦!因为我在考虑基于结构的解决方案;我修改了,修改了,修改了……地震了!可怕的洪水!蝗虫!这不是我的错! (好的:你是对的;简化了;谢谢!)
  • 实际上数组是类的私有元素,我更喜欢为它们使用非静态数据......所以我会坚持使用 Quentin 的解决方案;)但我从你的帖子中学到了,所以我我会赞成的:)
  • @Quentin :你说得对,我纠正了我在问题中的错误,但我显然无法编辑评论......所以这是给你的免费啤酒;)
【解决方案2】:

虽然@max66 的回答很棒,但如果您想要绝对最小的代码更改,您可以在 中执行此操作。

这不是必需的,但我喜欢清理类型:

template<class ReadType>
using handler_type = std::array<ReadType,   memory_handler_size>;
template<std::size_t S>
using handler_for_size = handler_type<ReadType<S>>;

handler_for_size<8> read_8_handler_;
handler_for_size<16> read_16_handler_;
handler_for_size<32> read_32_handler_;

然后initializeReadHandler:

template<size_t Size>
void initializeReadHandler(uint32_t begin,
                       uint32_t end,
                       ReadType<Size> func) {
  begin >>= 16;
  end >>= 16;
  for (uint32_t current = begin; current <= end; ++current) {
     auto& handler = std::get<handler_type<ReadType<Size>>( std::tie(read_8_handler_, read_16_handler_, read_32_handler_) );
     handler[current & 0xFFFF] = func;
  }
}

这里我们使用基于类型的get 和对零成本的引用获得正确的处理程序数组。

最大的不同是你可以留下你的全局read_8_handler_。如果没有理由使用全局read_8_handler_,请使用@max66 的答案。

【讨论】:

  • std::tie()/std::get() 的有趣用法。无论如何...我想优化器会自动执行此操作,但是...在for 循环之外定义/初始化handler 不是更好吗? (我想这在我的解决方案中也是如此......)
  • 我认为 max66 有道理,我将根据 Quentin 的答案编辑我的问题,并进行一些修复...
猜你喜欢
  • 1970-01-01
  • 2015-08-25
  • 2020-12-08
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
相关资源
最近更新 更多