I find myself needing to convert zero-based (or arbitrary) cartesian indices to one-based linear indices, such that, for instance, `indices[first(CartesianIndices((0:4,1:5)))] == 1`

. I could have used the sub2ind function for that, but that now seems to be private. Instead I ended up writing a new type that looks suspiciously similar to LinearIndices:

```
struct CartesianSpace{A,N} <: AbstractArray{Int,N}
axes::NTuple{N,A}
end
Base.axes(s::CartesianSpace) = s.axes
Base.IndexStyle(::Type{<:CartesianSpace}) = IndexLinear()
Base.size(s::CartesianSpace) = map(length, s.axes)
Base.getindex(s::CartesianSpace, i::Integer) = Int(i)
```

In fact the one significant difference is that axes(::LinearIndices) discards the original offset and always returns 1-based ranges. What’s the rationale for that? I’m confused that while Julia will let you build a LinearIndices((0:4,1:5)), this actually behaves as a LinearIndices((1:5,1:5)).