The documentation of (const) sheet_by_index already mentions that
invalid_parameter exception will be thrown if the index is out of
range, but the implementation was missing.
Previously, an empty row would mess with the parser: if we're in an
empty row, our helper methods don't detect us as being in the "row" _or_
in the "sheetData". So `has_cell()` would return false when it
shouldn't. Similarly, `read_cell()` wouldn't skip rows; so `read_cell()`
would return an invalid cell when placed in an empty row, causing a
segfault when the caller tried to use the cell.
Callers must take care to call `has_next()` before `read_next()`. In
the future, perhaps we can make `read_next()` return a `std::optional`
and nix `has_next()` altogether?
[Closes#492]
Otherwise, XLNT_INCLUDE_INSTALL_DIR is not set correctly and find_package(Xlnt) results to an error:
```
CMake Error at /usr/lib64/cmake/xlnt/XlntConfig.cmake:23 (message):
File or directory include referenced by variable XLNT_INCLUDE_DIR does not
exist !
Call Stack (most recent call first):
/usr/lib64/cmake/xlnt/XlntConfig.cmake:41 (set_and_check)
CMakeLists.txt:4 (find_package)
```
The content of the line 41 of /usr/lib64/cmake/xlnt/XlntConfig.cmake is: `set_and_check(XLNT_INCLUDE_DIR "include")`.
I'm using the Arch Linux user repository package https://aur.archlinux.org/packages/xlnt/.
The used build manual is described here: https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=xlnt.
the standard xlnt::cell and xlnt::cell_reference have plenty of extra functionality that just slows things down during (de)serialisation
These intermediate structs can be used to minimise overhead before transforming to the final type
user defined copy operators suppress compiler creation of move operations, and not having all of copy/move/dtor
defined (rule of 0/5) is suspicious. Also happens to be very slightly slower