【问题标题】:Convert std::variant to another std::variant with sub-set of types将 std::variant 转换为具有子集类型的另一个 std::variant
【发布时间】:2019-07-10 20:30:38
【问题描述】:

给定一个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?
}

我知道如何使用here 所述的访问者进行相反的操作(转换为超集变体),但这种方法不适用于这种情况。

【问题讨论】:

    标签: c++


    【解决方案1】:

    您可以简单地运行std::visit,使用接收 lambda 表达式,它只“吃”您想要的类型并创建新的变体类型。

    提示: 由于您转换的变体类型可能是“空的”,因为您必须返回一些东西,即使传入变体的类型不是您定义的有效类型,您也必须提供一些“虚拟类型”。为此,std::monotype 已被定义。

    使用 c++20 概念更容易,但我还为您提供了手工 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;
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 2021-03-25
      相关资源
      最近更新 更多