Мой вопрос касается возможности создания функции C ++ или аналогичной конструкции, которая возвращает имя типа (в отличие от объекта / ссылки / указателя некоторого типа, как это обычно бывает).
Как показано в приведенном ниже коде, у меня есть общий класс «Image», который просто содержит указатель на данные (void *), размер данных и переменную-член, определяющую способ представления данных. Мне нужна гибкость для представления 8-битных, 16-битных, ... типов изображений с одним и тем же классом.
Когда я хочу манипулировать данными изображения, я в настоящее время должен использовать конструкцию switch / case (какпоказанная в примере функция CopyImage()
) позволяет повторно интерпретировать указатель данных void * на соответствующий тип перед выполнением копирования. К сожалению, эта та же самая парадигма переключателя / случая повторяется повсюду, когда я расширяюсь функциями, которые делают что-то, кроме CopyImage (). Это кажется грязным и дублирующим и ограничивает мою способность добавлять поддержку для большего количества типов без репликации дополнительных случаев в тоннах других функций.
enum class datatype_t {
u8,
u16
};
class Image { // can be an image with 8 or 16-bit pixel representation
public:
void * dataPtr_;
datatype_t dataType_;
size_t pixels_;
};
void CopyImage(Image& source, uint16_t * dst_ptr) { // function to copy image agnostic to data represenation
switch (source.dataType_) {
case datatype_t::u8:
std::copy_n(reinterpret_cast<uint8_t*>(source.dataPtr_), source.pixels_, dst_ptr);
break;
case datatype_t::u16:
std::copy_n(reinterpret_cast<uint16_t*>(source.dataPtr_), source.pixels_, dst_ptr);
break;
}
}
int main()
{
const size_t image_size = 100;
std::vector<Image> image_library;
// create Image objects, populate details, push to image library
Image source_image8;
source_image8.dataType_ = datatype_t::u8;
source_image8.pixels_ = image_size;
source_image8.dataPtr_ = new uint8_t[image_size];
image_library.push_back(std::move(source_image8));
Image source_image16;
source_image16.dataType_ = datatype_t::u16;
source_image16.pixels_ = image_size;
source_image16.dataPtr_ = new uint16_t[image_size];
image_library.push_back(std::move(source_image16));
auto destination = new uint16_t[image_size];
CopyImage(image_library[0], destination); // copy a 8-bit image into 16-bit destination
CopyImage(image_library[1], destination); // copy a 16-bit image into 16-bit destination
// deletes, etc to follow (not shown for conciseness)
}
То, что я хочу - это функция, которую я могу включить в <...> из reinterpret_cast
, которая при вызове возвращает имя типа (то есть uint8_t, uint16_t), и т.д). Эта функция должна быть функцией-членом класса Image, ссылаться на переменную dataType_ и предоставлять имя типа - аналогично тому, что оператор switch / case делает явно для каждого возможного типа - но ее нужно поддерживать только в одном месте, так как онафункция, которая будет вызываться из любого места, где я пытаюсь выполнить операцию reinterpret_cast <>.
Например, функция с именем Image::ReturnType()
, которая может использоваться следующим образом:
std::copy_n(reinterpret_cast<source.ReturnType()>(source.dataPtr_), source.pixels_, dst_ptr);
и быть определена примерно так:
typename Image::ReturnType() {
switch (dataType_) {
case u8:
return uint8_t;
case u16:
return uint16_t;
}
}
Я понимаю этоВопрос заключается в том, чтобы попросить найти решение, которое использует преимущества полиморфизма или связано с шаблонизацией класса Image, так что у меня есть отдельные типы Image<uint8_t>
и Image<uint16_t>
, но это не позволяет мне хранить кучу объектов Image (с различными представлениями пикселей). ) в одном std::vector<Image>
.
Примечание. Если есть способ сохранить в одном std::vector
объекты с различными типами специализаций шаблонов, я также открыт для этого решения, но ябоюсь, что не существует.
Большое спасибо!