Возврат другого типа данных в зависимости от данных (C++)

Размер - это количество элементов, присутствующих в векторе

Емкость - это объем пространства, которое вектор использует в настоящее время.

Давайте разберемся с этим на простом примере:

using namespace std;

int main(){
  vector<int > vec;
  vec.push_back(1); 
  vec.push_back(1); 
  vec.push_back(1); 
  cout<<"size of vector"<<vec.size()<<endl;
  cout<<"capacity of vector"<<vec.capacity()<<endl;
  return 0;
}

в настоящее время размер равен 3, а емкость равна 4.

Теперь, если мы отодвинем еще один элемент,

using namespace std;
  int main(){
  vector<int> vec;
  vec.push_back(1); 
  vec.push_back(1); 
  vec.push_back(1); 
  vec.push_back(1);
  cout<<"size of vector"<<vec.size()<<endl;
  cout<<"capacity of vector"<<vec.capacity()<<endl;
  return 0;
}

теперь размер равен: 4 емкость равна 4

теперь, если мы попытаемся вставить еще один элемент в vector, то размер станет 5, но вместимость станет 8.

это происходит на основе типа данных vector, как здесь, в этом случае vector для типа int, так как мы знаем, что размер int составляет 4 байта, поэтому компилятор выделит 4 блока памяти .. и когда мы пытаемся добавить 5-й элемент, vector::capacity() удваивается, что мы имеем в настоящее время.

то же самое продолжайте .. например: если мы попытаемся вставить 9-й элемент, то размер vector будет 9, а емкость b 16 ..

9
задан Ayman Hourieh 31 May 2009 в 00:26
поделиться

5 ответов

Нет. Тип возвращаемого значения функции C ++ может изменяться только в зависимости от явных параметров шаблона или типов ее аргументов. Он не может изменяться в зависимости от значения его аргументов.

Однако вы можете использовать различные методы для создания типа, который является объединением нескольких других типов. К сожалению, это не обязательно поможет вам здесь, поскольку одна из таких техник сама по себе является void *, и вернуться к исходному типу будет сложно.

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

void bitmap_operation(void *data, int depth, int width, int height) {
  some_magical_type p_pixels = returnPointer(data, depth);
  for (int x = 0; x < width; x++)
    for (int y = 0; y < width; y++)
      p_pixels[y*width+x] = some_operation(p_pixels[y*width+x]);
}

Поскольку C ++ должен знать тип p_pixels во время компиляции, это не будет работать как есть. Но что мы можем сделать, так это сделать сам bitmap_operation шаблоном, а затем обернуть его переключателем в зависимости от глубины:

10
ответ дан 4 December 2019 в 11:43
поделиться

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

// template declaration
template<int depth>
struct uint_tmpl;

// specializations for certain types
template<> struct uint_tmpl<8>  { typedef uint8_t type; };
template<> struct uint_tmpl<16> { typedef uint16_t type; };
template<> struct uint_tmpl<32> { typedef uint32_t type; };

Это определение можно использовать для объявления шаблонной функции, которая возвращает правильный тип для каждого битового значения:

// generic declaration
template<int depth>
typename uint_tmpl<depth>::type* returnPointer(void* ptr);

// specializations for different depths
template<> uint8_t*  returnPointer<8>(void* ptr)  { return (uint8_t*)ptr;  }
template<> uint16_t* returnPointer<16>(void* ptr) { return (uint16_t*)ptr; }
template<> uint32_t* returnPointer<32>(void* ptr) { return (uint32_t*)ptr; }
7
ответ дан 4 December 2019 в 11:43
поделиться

Нет; вы не можете сделать это в C ++. Правильный ответ - вернуть void * .

Подумайте об этом с противоположной стороны вызова - и с точки зрения компилятора:

Как компилятор сможет проверить, правильно ли используется возвращаемое значение (например, присвоено переменной правильного типа), если он не может знать, какой из трех возвращаемых типов будет возвращен?

В этот момент понятие присваивания " один из нескольких типов "возвращаемого значения становится бессмысленным. У возвращаемого типа функции нет другой цели в жизни, кроме как дать компилятору возможность выполнять свою работу; компилятору нужен «один» тип, чтобы иметь возможность выполнять проверку типов. Поскольку вы не знаете, какой именно, до времени выполнения, компилятор может ' Я провожу проверку типов за вас. Вы должны сказать компилятору «прекратить попытки» сопоставить возвращаемое значение с любым конкретным типом указателя - следовательно, вернуть void * .

Если ваши аргументы глубины известны во время компиляции, вы в качестве альтернативы можно использовать набор шаблонов, таких как @sth , продемонстрированный, или использовать набор отдельных независимых функций, или использовать набор связанных функций, которые вызывают общую функцию реализации и затем приводят возвращаемый результат к правильному типу. Какой из них вы выберете - это в основном эстетическое решение.

Если значение depth не известно до времени выполнения, вам, вероятно, следует вернуть void * . ​​

Теперь я предполагаю, что ваша фактическая реализация действительно что-то делает для создания указателя, а не то, что показывает ваш пример кода. Ваш пример кода не является реальной функцией; это больше похоже на попытку повторить то, что делает приведение . Приведение не является вызовом функции; это директива компилятора, чтобы попытаться «преобразовать» его операнд в определенный тип (именно «как», это длинная история для другого поста). Это не операция языка C ++, а операция компилятора. Вы не можете переписать это на самом C ++.

0
ответ дан 4 December 2019 в 11:43
поделиться

You can allocate some memory on the heap, and return a void* that you cast to the type that was allocated. Its a dangerous and unsafe way of working and is an old C trick.

You could return a union that contains all valid datatypes (and a selection indicator).

You could use templates, which is the recommended C++ way for this kind of thing.

You could provide a set of overloaded functions that take a parameter (of each type) as a reference - the compiler will decide which function to call based on the datatype. I often prefer this way as I think its the simplest.

1
ответ дан 4 December 2019 в 11:43
поделиться

вы можете сделать это:

if (depth == 8) (uint8 *) returnPointer (void * ptr, int depth) {// etc

0
ответ дан 4 December 2019 в 11:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: