Please see code below.
I have 3 struct
s (A
, B
and C
) defined across 2 groups (in reality I have many more). The groups are to provide context within the real-world domain i'm modelling. These groups are implemented via two std::variant
s (Group1
and Group2
).
I have a function which can return any of the underlying struct
s.
To provide a single return type for the function I create a third std::variant
(AllGroups
) from my initial two variants (Group1
and Group2
).
However, my problem is AllGroups
cannot see A
, B
or C
, only Group1
and Group2
.
Is there a way to keep the structs defined with some sort of group but also collapse them in to one std::variant
for the function return type?
#include <variant>
#include <iostream>
struct A{}; struct B{};
using Group1 = std::variant<A, B>;
struct C{};
using Group2 = std::variant<C>;
using AllGroups = std::variant<Group1, Group2>;
AllGroups getObject()
{
A a; // Simple logic for the general question
AllGroups ret(a);
return ret;
}
int main()
{
AllGroups ret = getObject();
// Here i'd like to check for the individual structs, not Group1 and Group2
// However I get a compiler error because the AllVariant can only see Group1 and Group2
std::cout << std::holds_alternative<A>(ret) << std::endl;
}
Here is how you can do a trait which produces a type you want - a combination of variant's alternative types. Unlike the other answers, it works with more than two variants being joined ;)
#include <variant>
template<class Variant1, class Variant2, class... Variants>
struct variant_cat;
template<class... Var1, class... Var2>
struct variant_cat<std::variant<Var1...>, std::variant<Var2...>>
{
using type = std::variant<Var1..., Var2...>;
};
template<class... Var1, class... Var2, class... Variants>
struct variant_cat<std::variant<Var1...>, std::variant<Var2...>, Variants...>
{
using type = typename variant_cat<std::variant<Var1..., Var2...>, Variants...>::type;
};
template<class... A>
using variant_cat_t = variant_cat<A...>::type;
// Usage:
variant_cat_t<std::variant<int, char>, std::variant<double, float>, std::variant<std::nullptr_t>> Result;