Я работаю над рендерером, использующим OpenGL.
У меня есть первый класс, Geometry:
class Geometry
{
public:
void setIndices( const unsigned int* indices, int indicesCount );
private:
std::vector<unsigned char> colors;
std::vector<float> positions;
std::vector<unsigned int> indices;
};
Иногда, мои геометрии нужно запасать для своих индексов разного типа, данные могут быть:
1. std::vector<unsigned char>
2. std::vector<short>
3. std::vector<int>
// I've already think about std::vector<void>, but it sound dirty :/.
В настоящее время я использую unsigned int всюду, и я передаю свои данные, когда хочу установить его в мою геометрию:
const char* indices = { 0, 1, 2, 3 };
geometry.setIndices( (const unsigned int*) indices, 4 );
Позже я хотел бы обновить или прочитать этот массив во время выполнения (массив может содержать более 60000 индексов), поэтому я делаю что-то вроде этого:
std::vector<unsigned int>* indices = geometry.getIndices();
indices->resize(newIndicesCount);
std::vector<unsigned int>::iterator it = indices->begin();
Проблема в том, что мой цикл итератора на неподписанном массиве int, поэтому iterator имеет 4 байта до 4 байтов, мои исходные данные могут быть char (от 1 байт до 1 байт). Невозможно прочитать мои исходные данные или обновить его новыми данными.
Когда я хочу обновить свой вектор, мое единственное решение - создать новый массив, заполнить его данными, а затем передать его в массив unsigned int, я бы хотел повторить указатель на индексы.
Спасибо за ваше время!
Кастинг с неправильным типом указателя даст неопределенное поведение и, конечно же, потерпит неудачу, если, как здесь, тип имеет неправильный размер.
Как я могу сделать что-то общее (работа с unsigned int, char и short)?
Шаблон будет самым простым способом сделать этот общий:
template <typename InputIterator>
void setIndices(InputIterator begin, InputIterator end) {
indices.assign(begin, end);
}
Использование (исправление вашего примера использования массива, а не указателя):
const char indices[] = { 0, 1, 2, 3 };
geometry.setIndices(std::begin(indices), std::end(indices));
Вы можете рассмотреть удобную перегрузку, чтобы напрямую принимать контейнеры, массивы и другие типы диапазонов:
template <typename Range>
void setIndices(Range const & range) {
setIndices(std::begin(range), std::end(range));
}
const char indices[] = { 0, 1, 2, 3 };
geometry.setIndices(indices);
Как я могу перебирать массив без копирования?
Вы не можете изменить тип массива без копирования данных. Чтобы избежать копирования, вам придется ожидать правильного типа массива.