Типы в общедоступном C++ API

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

Учитывая функцию

void foo (int bar)

который ожидает индекс для некоторого внутреннего массива/контейнера. Какой это должен быть тип? Поскольку индекс никогда не может быть отрицательным, я мог бы использовать unsigned int или size_t. Или я должен придерживаться простого int и утверждать / бросать, если указано какое-то недопустимое значение?

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

РЕДАКТИРОВАТЬ: другой пример, предположим, что моя библиотека предоставляет функцию для печати файла. Пользователь может выбрать диапазон страниц для печати:

void print (int page_from, int page_to)

person cairol    schedule 03.12.2009    source источник


Ответы (3)


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

Когда вы попадаете в конкретную область приложения, size_t больше не является подходящим типом. В области вашего приложения этот индекс обычно имеет некоторую специфичную для приложения семантику, не связанную непосредственно с массивами. Например, это может быть какой-то «идентификатор сотрудника», или «номер сотового», или «цветовой индекс», или что-то еще. В таких случаях у вас обычно уже есть предварительно выбранный целочисленный тип для представления соответствующего количества. (И выбор обычно не будет иметь ничего общего с массивами.) Это именно тот тип, который вы должны использовать в своем интерфейсе.

Что касается знаковости/беззнаковости типа... Я, например, твердо верю, что беззнаковые величины должны быть представлены беззнаковыми типами, т.е. нормальный индекс массива должен быть беззнаковым.

person AnT    schedule 03.12.2009
comment
+1: сделайте typedef для количества, которое должно представлять число. - person avakar; 03.12.2009

Лучшим советом здесь, вероятно, будет придерживаться существующей практики (т.е. того, что делают стандартные библиотеки C++). Вообще говоря, это означает, по крайней мере, использование здесь типа unsigned; если вы на самом деле используете этот тип непосредственно как индекс массива/указателя (и ваша абстракция прозрачна в этом отношении), то может потребоваться size_t.

Если foo является функцией-членом некоторого класса, похожего на контейнер, то вы также можете подумать о том, чтобы typedef создать что-то вроде size_type и использовать его.

person Pavel Minaev    schedule 03.12.2009

Я голосую за использование unsigned. Еще лучше используйте stdint.h и что-то вроде uint32_t.

person Drakosha    schedule 03.12.2009
comment
В C++ нет stdint.h, и даже если бы он был, использование типа фиксированного размера неправильно. У вас может быть массив с более чем 2**32 элементами. (Кто сказал, что 640 КБ памяти должно быть достаточно для всех?) - person avakar; 03.12.2009
comment
en.wikipedia.org/wiki/Stdint.h› Я не предлагаю используя 32-битные целые числа, вы также можете использовать uint64_t, я предлагаю узнать, каков размер вашей переменной. - person Drakosha; 03.12.2009
comment
Спасибо за ссылку. Как я уже сказал, в C++ нет stdint.h. :) (Он был добавлен в C99, текущий стандарт C++ основан на C90. В следующей версии стандарта C++ будет представлено stdint.h. По крайней мере, один основной компилятор C++ еще не поддерживает его - msvc). В любом случае, я не думаю, что это хорошая идея - фиксировать размер ваших переменных, особенно если они ссылаются на индексы или размеры в памяти (которая имеет тенденцию к увеличению за все пределы). Я думал, что мы все усвоили этот урок во время 64-битного бума. - person avakar; 03.12.2009
comment
@Drakosha Я бы посоветовал вам не заботиться о точном размере ваших переменных, а только о том, что они достаточно велики. Обычно это означает использование int или long и предоставление компилятору возможности выбрать наиболее эффективное представление на данном оборудовании, возможно, добавление некоторых утверждений времени компиляции о том, что типы могут содержать требуемый диапазон значений. - person KeithB; 03.12.2009