将 std::variant 转换为另一个具有类型子集的 std::variant
Convert std::variant to another std::variant with sub-set of types
给定一个类型为 std::variant<A,B,C>
的变量,我已经检查过它不包含 C
。如何将其转换为std::variant<A,B>
?
std::variant<A,B> convert(std::variant<A,B,C> value) {
if (std::holds_alternative<C>(value)) {
// die.
}
return ... // what to do here?
}
我知道如何使用此处描述的访问者进行相反的操作(转换为超级集变体(,但这种方法不适用于这种情况。
您可以简单地运行槽std::visit
,使用仅"吃掉"所需类型的接收 lambda 表达式并创建新的变体类型。
提示:由于转换后的变体类型可能是"空的",因为您必须返回某些内容,即使传入变体中的类型在您的定义中不是有效的类型,您也必须提供一些"虚拟类型"。为此,已经定义了std::monotype
。
使用 c++20 概念会更容易,但我也为您提供了手工制作的 lambda 的"老式"方式:
struct A{};
struct B{};
struct C{};
using VARIANT_ALL = std::variant<A,B,C>;
using VARIANT_SUB = std::variant<std::monostate,A,B>;
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template < typename CHECK_ME >
concept IS_WANTED = std::is_same_v<CHECK_ME, A> || std::is_same_v<CHECK_ME, B >;
VARIANT_SUB GetSubset( const VARIANT_ALL& vin )
{
return std::visit( overloaded
{
[]( const A& x ){ return VARIANT_SUB{x};},
[]( const B& x ){ return VARIANT_SUB{x};},
[]( auto& ) { return VARIANT_SUB{};}
}, vin
);
}
VARIANT_SUB GetSubset2( const VARIANT_ALL& vin )
{
return std::visit( overloaded
{
[] < IS_WANTED TYPE >( const TYPE& x ){ return VARIANT_SUB{x};},
[]( auto& ) { return VARIANT_SUB{};}
}, vin
);
}
int main()
{
VARIANT_ALL va=A{};
VARIANT_ALL vb=B{};
VARIANT_ALL vc=C{};
auto vva = GetSubset( va );
auto vvb = GetSubset( vb );
auto vvc = GetSubset( vc );
std::cout << std::holds_alternative<A>( vva ) << std::endl;
std::cout << std::holds_alternative<B>( vvb ) << std::endl;
std::cout << std::holds_alternative<std::monostate>( vvc ) << std::endl;
auto vva2 = GetSubset2( va );
auto vvb2 = GetSubset2( vb );
auto vvc2 = GetSubset2( vc );
std::cout << std::holds_alternative<A>( vva2 ) << std::endl;
std::cout << std::holds_alternative<B>( vvb2 ) << std::endl;
std::cout << std::holds_alternative<std::monostate>( vvc2 ) << std::endl;
}
相关文章:
- 在template中使用std::variant的template函数
- 使用 std::variant<...时调用 BaseState 函数而不是派生函数>
- 为 std::variant 提供一个运算符 ==
- 如何使用 std::variant 打印地图键/值?
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- 在 std::tuple 上使用 std::variant 的问题
- 如何访问存储在 std::variant 中的类的方法
- 更改其类型后,丢失对 std::variant 对象的引用
- std::visit and std::variant usage
- std::variant vs指向C++中异构容器基类的指针
- std::variant<>::get() 不能使用 Apple LLVM 10.0 编译
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- 有没有办法避免为 std::variant 类成员中的所有类型编写构造函数?
- 按索引设置 std::variant 的值
- 在 std::variant 中按类型获取索引
- 与传统的多态处理相比,使用 std::variant 有什么优势?
- 无法引用该函数" std:: variant <_Types...> operator =",因为此函数已被删除
- 为什么 std::variant 找不到运算符<() 当与比较类不在同一命名空间中时
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 如何迭代 boost::variant<std::vector<int>, std::vector<String>>?