It's my understanding that std::variant
cannot directly hold references.
However, std::reference_wrapper
is a fully qualified type that can be put into things like std::vector
, and since one can make a vector of reference wrappers, I imagined that one could do the same with std::variant
.
The following (edited to be more minimal) code generates a plethora of errors in gcc:
#include <functional>
#include <variant>
class Foo;
class Baz;
template<typename T> struct CRef : std::reference_wrapper<const T> {
CRef(const T &x) : std::reference_wrapper<const T>(x)
{
}
};
template<typename... Args> struct Contains : public std::variant<CRef<Args>... > {
};
struct Foo : public Contains<Baz> {
int getSize() const;
};
struct getSizeVisitor {
template<typename T> int operator()(CRef<T> x) const
{
return sizeof(T);
}
};
inline int Foo::getSize() const
{
return std::visit(getSizeVisitor(), (*this));
}
struct Baz : public Foo {
};
The CRef
template is simply a convenient wrapper around an std::reference_wrapper to a const reference, and the Contains
template exists to help a class be made aware of all of the endpoint subclasses that the base class may at some point refer to. In the above case, I am simply wanting a getSize()
method, which will return the size of the actual type contained in the variant. Baz
, in this case, is the only endpoint class, although in practice there will be more, and they will have no common base class, which is why I require a variant, and cannot simply use a base class and employ virtual functions.
The errors generated by the compiler are visible here: https://godbolt.org/z/lcbPjB
So, I guess I'm probably doing something that isn't allowed.
The question I have is, is there a way to do what I'm trying? I apologize in advance if my intent is unclear. If there are problems understanding what I am trying to achieve, some feedback to that effect that specifically identifies what additional information I need to supply can be left and I shall endeavor to comply.
Bear in mind that in the actual use case, the endpoint classes are much more complex, and there will be many more functions beyond getSize(), but I expect once I have something working for this simple case, I should be able to generalize and implement the other functions correctly.