Приведение типов во время выполнения на основе размера в c ++ - PullRequest
0 голосов
/ 09 ноября 2011

Я пытаюсь восстановить тип массива в зависимости от размера его элементов. Я думаю, что я не могу использовать шаблоны для этого. Есть ли способ достичь этого без операторов switch? Или, если это невозможно без операторов switch, есть ли способ встроить оператор switch в класс (caster). Мне нравится идея класса кастера, потому что есть много функций, кроме копирования, которые нуждаются в подобном приведении.

copy_region(uint8_t *, int);
copy_region(uint16_t *, int);
copy_region(uint32_t *, int);

void copier(uint8_t *ptr_element, int sz_element) {
   copy_region( caster(sz_element, ptr_element), n);
}

Решение для переключения, которое у меня есть, выглядит следующим образом:

void copier(uint8_t *ptr_element, int sz_element) {
   switch(sz_element){
     case 1: copy_region( uint8_t*(ptr_element), n); break;
     case 2: copy_region( uint16_t*(ptr_element), n); break;
     case 4: copy_region( uint16_t*(ptr_element), n); break;
   }
}

Я также думал об определении операций как функторов, чтобы у меня мог быть один оператор switch, но параметры для различных операций очень различны.

Edit:

Информация о типе не теряется. Я пытаюсь реализовать систему (библиотека / фреймворк) с шаблонными буферами. У меня есть базовый буферный класс на основе uint8_t в качестве элемента. Этот класс существует, потому что мне нужно вставить буферы в список. Базовый класс буфера реализует операции над этими буферами. Пользователь указывает тип буфера в качестве аргумента шаблона для класса буфера, но библиотека видит только базовый класс буфера и информацию о типе (размер элемента достаточен для вывода типа).

Ответы [ 2 ]

4 голосов
/ 09 ноября 2011
template<int sz_element> void copier(uint8_t *ptr_element); //no definition
template<1> void copier(uint8_t *ptr_element)
{copy_region(uint8_t*(ptr_element), n);}
template<2> void copier(uint8_t *ptr_element)
{copy_region(uint16_t*(ptr_element), n);}
template<4> void copier(uint8_t *ptr_element)
{copy_region(uint32_t*(ptr_element), n);}
template<8> void copier(uint8_t *ptr_element)
{copy_region(uint64_t*(ptr_element), n);}

Если sz_element не известен во время компиляции, тогда вы должны использовать переключатель, который вы использовали в OP.

Хотя нет ничего хорошего, что может из этого выйти. Почему у вас есть uint8_t*, который указывает на произвольные данные? Избавься от этого.

[EDIT] Вы говорите, что у вас есть базовый класс, который является буфером uint8_t, и пользователи будут использовать унаследованные классы с информацией о типе. В этом случае, чтобы иметь вменяемый код, вам нужны виртуальные функции:

class base {
   vector<uint8_t> buffer;
public:
   virtual void copy()=0;
   virtual ~base() {}
};
template <class type>
class derived : public base {
public:
   virtual void copy() {}
   ~derived() {}
};

Это позволит вашей библиотеке использовать функции, не зная типов, но информация о типах не теряется.

2 голосов
/ 09 ноября 2011

Я думаю, что вместо того, чтобы пытаться достичь того, что вы хотите здесь сделать, вам следует переосмыслить свой дизайн. Перейдите к источнику и запишите тип массива в специальной переменной в начале вашего блока памяти - или, если возможно, сохраните тип указателя, который вы передаете, в качестве исходного типа массива, чтобы вы могли принудительно установить тип безопасность лучше.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...