vec[1] is equivalent to vec[vec.size()] at that point and thus not a valid
element of the vector, making the use of operator[] undefined behavior here.
With some compiler flags (like those used in package builds on RHEL and
similar), the compiler (rightfully) aborts the program on this out of bounds
access:
68/178 Test #68: base-base_string/vector_move ............................................***Failed 0.01 sec
/usr/include/c++/14/bits/stl_vector.h:1130: std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[](size_type) [with _Tp = icinga::String; _Alloc = std::allocator<icinga::String>; reference = icinga::String&; size_type = long unsigned int]: Assertion '__n < this->size()' failed.
Running 1 test case...
unknown location(0): fatal error: in "base_string/vector_move": signal: SIGABRT (application abort requested)
/builds/packages/icinga2/packaging/fedora/41/BUILD/icinga2-2.14.5+467.g206d7cda1-build/icinga2-2.14.5+467.g206d7cda1/test/base-string.cpp(120): last checkpoint
*** 1 failure is detected in the test module "icinga2"
This commit fixes this by taking the indirection through .data() and using
plain pointer arithmetic instead.
The move `String(Value&&)` constructor tries to partially move `String`
values from a `Value` type. However, since there was no an appropriate
`Value::Get<T>()` implementation that binds to the requested move
operation, the compiler will actually not move the value but copy it
instead as the only available implementation of `Value::Get<T>()`
returns a const reference `const T&`. This commit adds a new overload
that returns a non-const reference and allows to optionally move the string
value of a Value type.