Yes, and this could be useful in some cases.
Suppose you have a program that wishes to access more storage than will fit in virtual memory. By creating an allocator that references memory mapped storage and mapping it as required when indirecting
pointer objects, you can access arbitrarily large amounts of memory.
This remains conformant to 18.2:6 because
size_t is defined as large enough to contain the size of any object, but 188.8.131.52:2 table 28 defines
size_type as containing the size of the largest object in the allocation model, which need not be an actual object in the C++ memory model.
Note that the requirements in 184.108.40.206:2 table 28 do not constitute a requirement that the allocation of multiple objects should result in an array; for
allocate(n) the requirement is:
Memory is allocated for
nobjects of type
deallocate the assertion is:
Tobjects in the area
pointed to by
destroyed prior to this call.
Note area, not array. Another point is 220.127.116.11:4:
X::const_void_pointertypes shall satisfy
the requirements of NullablePointer (18.104.22.168). No constructor, comparison operator, copy operation,
move operation, or swap operation on these types shall exit via an exception.
X::const_pointershall also satisfy the requirements for a random access iterator (24.2).
There is no requirement here that
(&*p) + n should be the same as
p + n.
It’s perfectly legitimate for a model expressible within another model to contain objects not representable in the outer model; for example, non-standard models in mathematical logic.