Replace gmx::Any with std::any or std::variant
We should replace our use of gmx::Any
with a std C++17 component, such as potentially either std::any
or std::variant
. Some of our use cases have a known set of types and are thus suitable for std::variant (which also avoids heap allocation).
The KeyValueTreeValue
case is harder because there is a circularity of use. It can contain a KeyValueTreeArray
which does contain a vector of KeyValueTreeValue
. If KeyValueTreeValue
would use a variant, then both would require a complete (not forward) definition of the other, which can't be done. (That issue could be worked around by introducing some heap allocation.)
std::any
suits this use case (and likely uses the heap in the solution), however libstdc++ has at least one bug. KeyValueTreeObject
needs to make a std::pair
(to use with std::map
) that contains a KeyValueTreeValue
. The bug I've identified relates to being able to tell if KeyValueTreeValue
is constructible when it contains a std::any
and is fixed in 9.4 or 10.1 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90415). We can work around it e.g. with clang using a buggy libstdc++. But I ran into further problems with gcc 9.3 using buggy libstdc++ with KeyValueTreeArrayBuilderBase
being unable to identify KeyValueTreeObject
as either being move-insertable or not, in the implementation of the above-mentioned vector. gcc 10 has no problem with anything.
Unfortunately, the gmx::Any
used in the KVT stuff needs to interact with the options framework. One can find the typeid of the thing contained in either gmx::Any
or std::any/variant
but that's not enough to transfer the contained object from one type of any or variant to another. So we can't just leave gmx::Any
only for the KVT stuff and convert the rest.
Thus, until we require gcc 9.4 or higher (and libstdc++ 9.4 or higher with clang), we're stuck with gmx::Any
. I'll push up a branch with my WIP for that future happy day (https://gitlab.com/gromacs/gromacs/-/tree/3951-replace-gmx-any-with-std-any).