C++ 将结构分隔到 "groups" 但允许 `std::variant` 查看 "groups" 中的所有结构
C++ separate structs in to "groups" but allow `std::variant` to see all structs across the "groups"
请看下面的代码。
我在 2 个组中定义了 3 个 struct
(A
、B
和 C
)(实际上我还有更多)。这些小组将在我正在建模的现实世界领域内提供上下文。这些组是通过两个 std::variant
实现的(Group1
和 Group2
)。
我有一个函数可以 return 任何底层 struct
s。
为了为函数提供单一 return 类型,我从最初的两个变体(Group1
和 Group2
).
但是,我的问题是AllGroups
看不到A
、B
或C
,只能看到Group1
和Group2
。
有没有一种方法既可以保持用某种组定义的结构,又可以将它们折叠成一个 std::variant
用于函数 return 类型?
#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;
}
您可以使用特征将 std::variant<A...>
与 std::variant<B...>
组合以获得 std::variant<A...,B...>
:
#include <variant>
#include <iostream>
struct A{}; struct B{};
using Group1 = std::variant<A, B>;
struct C{};
using Group2 = std::variant<C>;
template <typename T1,typename T2> struct combine_variants;
template <typename... A,typename... B>
struct combine_variants<std::variant<A...>,std::variant<B...>> {
using type = std::variant<A...,B...>;
};
using AllGroups = combine_variants<Group1, Group2>::type;
AllGroups getObject()
{
A a; // Simple logic for the general question
AllGroups ret(a);
return ret;
}
int main()
{
AllGroups ret = getObject();
std::cout << std::holds_alternative<A>(ret) << std::endl;
}
这是另一种将两个变体类型连接在一起以获得合并类型的方法
template <typename... Ts, typename... Us>
auto variant_concat(std::variant<Ts...>, std::variant<Us...>) -> std::variant<Ts..., Us...>;
template <typename V1, typename V2>
using variant_concat_t = decltype(variant_concat(std::declval<V1>(), std::declval<V2>()));
你会像
一样使用它
using AllGroups = variant_concat_t<Group1, Group2>;
这里是你如何做一个特征来产生你想要的类型 - 变体的替代类型的组合。与其他答案不同,它适用于连接两个以上的变体;)
#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;
请看下面的代码。
我在 2 个组中定义了 3 个 struct
(A
、B
和 C
)(实际上我还有更多)。这些小组将在我正在建模的现实世界领域内提供上下文。这些组是通过两个 std::variant
实现的(Group1
和 Group2
)。
我有一个函数可以 return 任何底层 struct
s。
为了为函数提供单一 return 类型,我从最初的两个变体(Group1
和 Group2
).
但是,我的问题是AllGroups
看不到A
、B
或C
,只能看到Group1
和Group2
。
有没有一种方法既可以保持用某种组定义的结构,又可以将它们折叠成一个 std::variant
用于函数 return 类型?
#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;
}
您可以使用特征将 std::variant<A...>
与 std::variant<B...>
组合以获得 std::variant<A...,B...>
:
#include <variant>
#include <iostream>
struct A{}; struct B{};
using Group1 = std::variant<A, B>;
struct C{};
using Group2 = std::variant<C>;
template <typename T1,typename T2> struct combine_variants;
template <typename... A,typename... B>
struct combine_variants<std::variant<A...>,std::variant<B...>> {
using type = std::variant<A...,B...>;
};
using AllGroups = combine_variants<Group1, Group2>::type;
AllGroups getObject()
{
A a; // Simple logic for the general question
AllGroups ret(a);
return ret;
}
int main()
{
AllGroups ret = getObject();
std::cout << std::holds_alternative<A>(ret) << std::endl;
}
这是另一种将两个变体类型连接在一起以获得合并类型的方法
template <typename... Ts, typename... Us>
auto variant_concat(std::variant<Ts...>, std::variant<Us...>) -> std::variant<Ts..., Us...>;
template <typename V1, typename V2>
using variant_concat_t = decltype(variant_concat(std::declval<V1>(), std::declval<V2>()));
你会像
一样使用它using AllGroups = variant_concat_t<Group1, Group2>;
这里是你如何做一个特征来产生你想要的类型 - 变体的替代类型的组合。与其他答案不同,它适用于连接两个以上的变体;)
#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;