Если клиентский код может видеть только Foo
(что является идиомой pimpl), тогда нет смысла определять конкретный size_type
в конкретной реализации - он не будет виден / доступен для клиента тем не мение. Стандартные контейнеры могут это делать, поскольку они построены на так называемом «полиморфизме во время компиляции», в то время как вы специально пытаетесь использовать [потенциально] метод сокрытия реализации во время выполнения.
В вашей ситуации единственным выбором будет выбор целочисленного типа, которого «должно быть достаточно для всех возможных реализаций» (например, unsigned long
), и придерживайтесь его.
Другой возможностью является использование типа uintptr_t
, если он доступен в вашей реализации (он стандартизирован в C99, но не в C ++). Предполагается, что этот целочисленный тип охватывает весь диапазон адресов хранения, доступный программе, что означает, что его всегда будет достаточно для представления размера любого контейнера в памяти. Обратите внимание, что другие постеры часто используют ту же логику, но неправильно приходят к выводу, что подходящий тип для использования здесь - size_t
. (Обычно это происходит из-за недостатка опыта реализации моделей не плоской памяти.) Если ваши контейнеры всегда основаны на физических массивах, size_t
будет работать. Однако, если ваши контейнеры не всегда основаны на массивах, size_t
даже не является удаленно правильным типом для использования здесь, так как его диапазон обычно меньше, чем максимальный размер не непрерывного (не основанного на массиве) контейнера.
Но в любом случае, независимо от того, какого размера вы в конечном итоге используете, было бы неплохо спрятать его за typedef-именем, как это делается в стандартных контейнерах.