You can simply run trough std::visit
, use a receiving lambda expression which only "eats" the type you want and create your new variant type.
Hint:
As your converted variant type is maybe "empty", because you have to return something, even if the type from the incoming variant is not a valid one by your definition, you have to provide some "dummy type". For this purpose std::monotype
is already defined.
Using a c++20 concept makes it easier, but I provide you also the "old fashioned" way with handcrafted lambdas:
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;
}