Замените массивы указателей на функции, используя шаблоны в современном c ++ - PullRequest
0 голосов
/ 28 октября 2018

У меня есть какой-то устаревший код, использующий массивы указателей функций для эмуляции обработчиков памяти.
Так что я сейчас пытаюсь использовать ту же функциональность, используя шаблоны.
Вот что я пробовал до сих пор:

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, так как не могу позволить себе снизить производительность...

... EDIT ...
Вот код, основанный на ответе Якка, 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 Спасибо, ребята!

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

Хотя ответ @ 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.

0 голосов
/ 28 октября 2018

Если я правильно понимаю, и вы не хотите поддерживать read_8_handler_, read_16_handler_ и read_32_handler_ глобальные переменные (своего рода), я полагаю, вы можете обернуть их как статические переменные внутри шаблонных функций (сильно упрощенных после квентинскихпредложение)

Что-то вроде

 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;
    }
}

Но, если возможно, япредлагаю вам передать массив (по ссылке) в качестве аргумента функции.

...