总体结构 
variant 
首先是variant的结构,variant的模板声明长这样:
1 2 3 4 5 6 7 8 9 10 11 12 template <typename ... _Types>  class  variant    : private  __detail::__variant::_Variant_base<_Types...>,     private  _Enable_default_constructor<       __detail::__variant::_Traits<_Types...>::_S_default_ctor,         variant<_Types...>>,     private  _Enable_copy_move<       __detail::__variant::_Traits<_Types...>::_S_copy_ctor,       __detail::__variant::_Traits<_Types...>::_S_copy_assign,       __detail::__variant::_Traits<_Types...>::_S_move_ctor,       __detail::__variant::_Traits<_Types...>::_S_move_assign,       variant<_Types...>> 
 
_Enable_copy_move在上一篇optional解析 中解释了,这里不同之处在于要考察variant的模板参数包内多个类型的可复制性、可移动性,如果其中某个类型不可复制或不可移动,那么variant亦不可复制或不可移动。 
_Enable_default_constructor为用于生成默认构造的helper模板,代码长这样:
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 template <bool  _Switch, typename  _Tag = void >  struct  _Enable_default_constructor   {     constexpr  _Enable_default_constructor() noexcept  = default ;     constexpr  _Enable_default_constructor(_Enable_default_constructor const &)       noexcept   = default ;     constexpr  _Enable_default_constructor(_Enable_default_constructor&&)       noexcept  = default ;     _Enable_default_constructor&     operator =(_Enable_default_constructor const &) noexcept  = default ;     _Enable_default_constructor&     operator =(_Enable_default_constructor&&) noexcept  = default ;          constexpr  explicit      _Enable_default_constructor(_Enable_default_constructor_tag) { }   }; 
 
当然它也有一个_Switch为false的特化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 template <typename  _Tag>  struct  _Enable_default_constructor <false , _Tag>   {     constexpr  _Enable_default_constructor() noexcept  = delete ;     constexpr  _Enable_default_constructor(_Enable_default_constructor const &)       noexcept   = default ;     constexpr  _Enable_default_constructor(_Enable_default_constructor&&)       noexcept  = default ;     _Enable_default_constructor&     operator =(_Enable_default_constructor const &) noexcept  = default ;     _Enable_default_constructor&     operator =(_Enable_default_constructor&&) noexcept  = default ;          constexpr  explicit      _Enable_default_constructor(_Enable_default_constructor_tag) { }   }; 
 
对于variant其默认空构要求保有第一个类型的值,所以就要求第一个类型必须有默认空构:
1 2 3 4 5 6 7 8 9 10 11 template <typename ... _Types>  struct  _Traits    {     static  constexpr  bool  _S_default_ctor =       is_default_constructible_v<typename  _Nth_type<0 , _Types...>::type>;        } template <typename  _Tp0, typename ... _Rest>  struct  _Nth_type <0 , _Tp0, _Rest...>   { using  type = _Tp0; }; 
 
_Variant_base 
与其他stl模板类似,variant的实现主要在基类中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 template <typename ... _Types>  struct  _Variant_base  : _Move_assign_alias<_Types...>   {     using  _Base = _Move_assign_alias<_Types...>;     constexpr      _Variant_base() noexcept (_Traits<_Types...>::_S_nothrow_default_ctor)     : _Variant_base(in_place_index<0 >) { }     template <size_t  _Np, typename ... _Args>       constexpr  explicit        _Variant_base(in_place_index_t <_Np> __i, _Args&&... __args)       : _Base(__i, std::forward<_Args>(__args)...)       { }     _Variant_base(const  _Variant_base&) = default ;     _Variant_base(_Variant_base&&) = default ;     _Variant_base& operator =(const  _Variant_base&) = default ;     _Variant_base& operator =(_Variant_base&&) = default ;   }; 
 
特殊成员函数套娃 
这里存在几个套娃似的的结构用于解决实际存储的复制构造、移动构造、复制赋值、移动赋值问题,首先是移动赋值,_Variant_base继承的_Move_assign_alias相关代码:
1 2 3 4 5 6 7 8 9 10 11 template <typename ... _Types>  using  _Move_assign_alias =     _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>; template <typename ... _Types>  struct  _Traits    {     static  constexpr  bool  _S_trivial_move_assign =         _S_trivial_dtor && _S_trivial_move_ctor         && (is_trivially_move_assignable_v<_Types> && ...);   } 
 
_Move_assign_base按实际参数包是否可移动赋值,分别为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 template <bool , typename ... _Types>  struct  _Move_assign_base  : _Copy_assign_alias<_Types...>   {     using  _Base = _Copy_assign_alias<_Types...>;     using  _Base::_Base;     _GLIBCXX20_CONSTEXPR     _Move_assign_base&     operator =(_Move_assign_base&& __rhs)       noexcept (_Traits<_Types...>::_S_nothrow_move_assign)     {       __variant::__raw_idx_visit(         [this ](auto && __rhs_mem, auto  __rhs_index) mutable          {           constexpr  size_t  __j = __rhs_index;           if  constexpr  (__j != variant_npos)             {               if  (this ->_M_index == __j)                 __variant::__get<__j>(*this ) = std::move (__rhs_mem);               else                  {                   using  _Tj = typename  _Nth_type<__j, _Types...>::type;                   if  constexpr  (is_nothrow_move_constructible_v<_Tj>)                     __variant::__emplace<__j>(*this , std::move (__rhs_mem));                   else                      {                       using  _Variant = variant<_Types...>;                       _Variant& __self = __variant_cast<_Types...>(*this );                       __self.template  emplace <__j>(std::move (__rhs_mem));                     }                 }             }           else              this ->_M_reset();         }, __variant_cast<_Types...>(__rhs));       return  *this ;     }     _Move_assign_base(const  _Move_assign_base&) = default ;     _Move_assign_base(_Move_assign_base&&) = default ;     _Move_assign_base& operator =(const  _Move_assign_base&) = default ;   }; template <typename ... _Types>  struct  _Move_assign_base <true , _Types...> : _Copy_assign_alias<_Types...>   {     using  _Base = _Copy_assign_alias<_Types...>;     using  _Base::_Base;   }; 
 
即在参数不可移动赋值时使用自定义的赋值操作,这里先不管这些移动、复制操作,先来看看最终的存储,省略中间套娃代码来到:
_Variant_storage 
1 2 3 4 5 6 7 8 9 template <typename ... _Types>  using  _Variant_storage_alias =       _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>; template <bool , typename ... _Types>  struct  _Copy_ctor_base  : _Variant_storage_alias<_Types...>   {          } 
 
然后又到了是否平凡析构的环节…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 template <typename ... _Types>  struct  _Traits    {     static  constexpr  bool  _S_trivial_dtor =         (is_trivially_destructible_v<_Types> && ...);   } template <bool  __trivially_destructible, typename ... _Types>  struct  _Variant_storage ; template <typename ... _Types>  struct  _Variant_storage <false , _Types...>   {     constexpr      _Variant_storage()     : _M_index(static_cast <__index_type>(variant_npos))     { }     template <size_t  _Np, typename ... _Args>       constexpr        _Variant_storage(in_place_index_t <_Np>, _Args&&... __args)       : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),       _M_index{_Np}       { }     constexpr  void      _M_reset()     {       if  (!_M_valid()) [[unlikely]]         return ;       std::__do_visit<void >([](auto && __this_mem) mutable          {           std::_Destroy(std::__addressof(__this_mem));         }, __variant_cast<_Types...>(*this ));       _M_index = static_cast <__index_type>(variant_npos);     }     _GLIBCXX20_CONSTEXPR     ~_Variant_storage()     { _M_reset(); }     constexpr  bool      _M_valid() const  noexcept      {       if  constexpr  (__variant::__never_valueless<_Types...>())          return  true  ;      return  this ->_M_index != __index_type(variant_npos);     }     _Variadic_union<_Types...> _M_u;     using  __index_type = __select_index<_Types...>;     __index_type _M_index;   }; template <typename ... _Types>  struct  _Variant_storage <true , _Types...>   {     constexpr      _Variant_storage()     : _M_index(static_cast <__index_type>(variant_npos))     { }     template <size_t  _Np, typename ... _Args>       constexpr        _Variant_storage(in_place_index_t <_Np>, _Args&&... __args)       : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),       _M_index{_Np}       { }     constexpr  void      _M_reset() noexcept      { _M_index = static_cast <__index_type>(variant_npos); }     constexpr  bool      _M_valid() const  noexcept      {       if  constexpr  (__variant::__never_valueless<_Types...>())          return  true  ;                                                return  this ->_M_index != static_cast <__index_type>(variant_npos);     }     _Variadic_union<_Types...> _M_u;     using  __index_type = __select_index<_Types...>;     __index_type _M_index;   }; 
 
两个特化区别在于析构时的选择,但两个都包含相同的数据成员_M_u与_M_index,先来看这个_Variadic_union:
_Variadic_union 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44      template <typename ... _Types>     union  _Variadic_union      {       _Variadic_union() = default ;       template <size_t  _Np, typename ... _Args>         _Variadic_union(in_place_index_t <_Np>, _Args&&...) = delete ;     };   template <typename  _First, typename ... _Rest>     union  _Variadic_union <_First, _Rest...>     {       constexpr  _Variadic_union() : _M_rest() { }       template <typename ... _Args>         constexpr          _Variadic_union(in_place_index_t <0 >, _Args&&... __args)         : _M_first(in_place_index<0 >, std::forward<_Args>(__args)...)         { }       template <size_t  _Np, typename ... _Args>         constexpr          _Variadic_union(in_place_index_t <_Np>, _Args&&... __args)         : _M_rest(in_place_index<_Np-1 >, std::forward<_Args>(__args)...)         { } #if  __cpp_lib_variant >= 202106L       _Variadic_union(const  _Variadic_union&) = default ;       _Variadic_union(_Variadic_union&&) = default ;       _Variadic_union& operator =(const  _Variadic_union&) = default ;       _Variadic_union& operator =(_Variadic_union&&) = default ;       ~_Variadic_union() = default ;       constexpr  ~_Variadic_union()         requires  (!__has_trivial_destructor(_First))               || (!__has_trivial_destructor(_Variadic_union<_Rest...>))       { } #endif        _Uninitialized<_First> _M_first;       _Variadic_union<_Rest...> _M_rest;     }; 
 
这是个递归定义的template union,上面的_Variadic_union是无类型参数时的template,下面的则是递归定义。_Uninitialized<_First> _M_first是递归定义中这一层的实际值,_Variadic_union<_Rest...> _M_rest递归定义剩余参数包,_M_first与_M_rest共享一块内存。 
来看看_Uninitialized:
_Uninitialized 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92                     template <typename  _Type, bool  = std::is_trivially_destructible_v<_Type>>     struct  _Uninitialized;   template <typename  _Type>     struct  _Uninitialized <_Type, true >     {       template <typename ... _Args>         constexpr          _Uninitialized(in_place_index_t <0 >, _Args&&... __args)         : _M_storage(std::forward<_Args>(__args)...)         { }       constexpr  const  _Type& _M_get() const  & noexcept        { return  _M_storage; }       constexpr  _Type& _M_get() & noexcept        { return  _M_storage; }       constexpr  const  _Type&& _M_get() const  && noexcept        { return  std::move (_M_storage); }       constexpr  _Type&& _M_get() && noexcept        { return  std::move (_M_storage); }       _Type _M_storage;     };   template <typename  _Type>     struct  _Uninitialized <_Type, false >     { #if  __cpp_lib_variant >= 202106L       template <typename ... _Args>         constexpr          _Uninitialized(in_place_index_t <0 >, _Args&&... __args)         : _M_storage(std::forward<_Args>(__args)...)         { }       constexpr  ~_Uninitialized() { }       _Uninitialized(const  _Uninitialized&) = default ;       _Uninitialized(_Uninitialized&&) = default ;       _Uninitialized& operator =(const  _Uninitialized&) = default ;       _Uninitialized& operator =(_Uninitialized&&) = default ;       constexpr  const  _Type& _M_get() const  & noexcept        { return  _M_storage; }       constexpr  _Type& _M_get() & noexcept        { return  _M_storage; }       constexpr  const  _Type&& _M_get() const  && noexcept        { return  std::move (_M_storage); }       constexpr  _Type&& _M_get() && noexcept        { return  std::move (_M_storage); }       struct  _Empty_byte  { };       union  {         _Empty_byte _M_empty;         _Type _M_storage;       }; #else        template <typename ... _Args>         constexpr          _Uninitialized(in_place_index_t <0 >, _Args&&... __args)           {           ::new  ((void *)std::addressof (_M_storage))             _Type(std::forward<_Args>(__args)...);         }       const  _Type& _M_get() const  & noexcept        { return  *_M_storage._M_ptr(); }       _Type& _M_get() & noexcept        { return  *_M_storage._M_ptr(); }       const  _Type&& _M_get() const  && noexcept        { return  std::move (*_M_storage._M_ptr()); }       _Type&& _M_get() && noexcept        { return  std::move (*_M_storage._M_ptr()); }       __gnu_cxx::__aligned_membuf<_Type> _M_storage; #endif      }; 
 
根据类型是否可平凡析构特化了两个版本的_Uninitialized,可平凡析构时_Uninitialized即是类型_Type的简单封装; 
不可平凡析构且标准为c++17时实际存储为__gnu_cxx::__aligned_membuf<_Type>,__aligned_membuf是gcc内常用的内存对齐缓冲,该类型内包含一个实际存储对象的字节数组,构造、析构都不操作实际对象,所以上述代码①处使用了placement new构造实际对象,当前场景的_Uninitialized也由编译器生成平凡析构不对实际对象进行析构; 
不可平凡析构且为c++20以后标准时,这里由于c++20标准后constexpr变量必须拥有constexpr析构(所谓常量析构),__aligned_membuf不具备常量析构,所以这里另写了个分支。该场景下使用一个带有_Empty_byte的union控制存储,并提供一个非平凡的常量析构,且这个析构并不析构内在对象,实际对象的析构由外部控制。 
所以_Variadic_union即一个可变参数union,不难猜出_Variant_storage中的__index_type即是表明当前union存在项的索引,这里展开下前面的using __index_type = __select_index<_Types...>,把相关代码贴下:
__select_index 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51   template  <typename ... _Types>     using  __select_index =       typename  __select_int::_Select_int_base<sizeof ...(_Types),                                               unsigned  char ,                                               unsigned  short >::type::value_type;   template <unsigned  long  long  _Val, typename  _IntType, typename ... _Ints>     struct  _Select_int_base <_Val, _IntType, _Ints...>     : __conditional_t <(_Val <= __gnu_cxx::__int_traits<_IntType>::__max),                       integral_constant<_IntType, (_IntType)_Val>,                       _Select_int_base<_Val, _Ints...>>     { };   template <bool  _Cond, typename  _If, typename  _Else>     using  __conditional_t        = typename  __conditional<_Cond>::template  type<_If, _Else>;   template <bool >     struct  __conditional      {       template <typename  _Tp, typename >         using  type = _Tp;     };   template <>     struct  __conditional <false >     {       template <typename , typename  _Up>         using  type = _Up;     };      template <typename  _Tp, _Tp __v>     struct  integral_constant      {       static  constexpr  _Tp                  value = __v;       typedef  _Tp                           value_type;       typedef  integral_constant<_Tp, __v>   type;       constexpr  operator  value_type ()  const  noexcept   { return  value; } #if  __cplusplus > 201103L #define  __cpp_lib_integral_constant_callable 201304L       constexpr  value_type operator () ()  const  noexcept   { return  value; } #endif      };      struct  _Select_int_base <sizeof ...(_Types), unsigned  char , unsigned  short >   : __conditional_t <(sizeof ...(_Types) <= __gnu_cxx::__int_traits<_unsigned char >::__max),                     integral_constant<unsigned  char , (unsigned  char )sizeof ...(_Types)>,                     _Select_int_base<sizeof ...(_Types), unsigned  short >> 
 
__conditional_t是条件模板,即当第一个模板参数成立时该模板为_If否则为_Else,亦即当参数包所占小于unsigned char最大值时继承integral_constant<unsigned char, (unsigned char)sizeof...(_Types)>否则继承integral_constant<unsigned short, (unsigned short)sizeof...(_Types)>,而integral_constant<_Tp, __v>::type::value_type其实也就是_Tp。所以__index_type类型即是unsigned char或是unsigned short。
结构图 
到此已经差不多把std::variant结构过了一遍,这里以std::variant<int, float, string> va{std::in_place_index<2>, "str in variant"}为例,来看看gdb中看到的结构: 
 
三个_Variadic_union共享内存: 
成员函数 
构造函数 
默认构造 
继承链底层的variant将五个特殊成员及空构都声明为=default:
1 2 3 4 5 6 variant () = default ;variant (const  variant& __rhs) = default ;variant (variant&&) = default ;variant& operator =(const  variant&) = default ; variant& operator =(variant&&) = default ; _GLIBCXX20_CONSTEXPR ~variant () = default ; 
 
默认空构时构造父类_Variant_base:
1 2 3 4 5 6 7 8 9 10 using  _Base = _Move_assign_alias<_Types...>;constexpr _Variant_base() noexcept (_Traits<_Types...>::_S_nothrow_default_ctor) : _Variant_base(in_place_index<0 >) { } template <size_t  _Np, typename ... _Args>  constexpr  explicit    _Variant_base(in_place_index_t <_Np> __i, _Args&&... __args)   : _Base(__i, std::forward<_Args>(__args)...)   { } 
 
中间的_Move_assign_alias四个套娃类只各自解决一个特殊成员函数,最终"_Base"的构造会来到_Variant_storage:
1 2 3 4 5 6 template <size_t  _Np, typename ... _Args>  constexpr    _Variant_storage(in_place_index_t <_Np>, _Args&&... __args)   : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...),   _M_index{_Np}   { } 
 
构造_Variadic_union:
1 2 3 4 5 template <typename ... _Args>  constexpr    _Variadic_union(in_place_index_t <0 >, _Args&&... __args)   : _M_first(in_place_index<0 >, std::forward<_Args>(__args)...)   { } 
 
构造_Uninitialized:
1 2 3 4 5 template <typename ... _Args>  constexpr    _Uninitialized(in_place_index_t <0 >, _Args&&... __args)   : _M_storage(std::forward<_Args>(__args)...)   { } 
 
默认构造时构造第一个元素,_Variant_storage的_M_index构造为0。
in_place_index构造 
来看看另一个指定index的构造,variant:
1 2 3 4 5 6 7 8 template <size_t  _Np, typename ... _Args,         typename  _Tp = __to_type<_Np>,          typename  = enable_if_t <is_constructible_v<_Tp, _Args...>>>   constexpr  explicit    variant (in_place_index_t <_Np>, _Args&&... __args)   : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...),   _Default_ctor_enabler(_Enable_default_constructor_tag{})   { } 
 
_Default_ctor_enabler是上面提到的_Enable_default_constructor的别名,这里就是标识这个父类是经由非默认构造函数进行构造。 
_Base的构造和默认构造类似,只是这里的_Np是由函数模板参数指定,到_Variadic_union中时经由另一个函数模板来完成构造:
1 2 3 4 5 template <size_t  _Np, typename ... _Args>  constexpr    _Variadic_union(in_place_index_t <_Np>, _Args&&... __args)   : _M_rest(in_place_index<_Np-1 >, std::forward<_Args>(__args)...)   { } 
 
这样在多嵌套层_Variadic_union中经由多次模板函数调用找到对应index的_M_first完成构造。
析构函数 
主要析构在于_Variant_storage中,关注下当实际类型不可平凡析构时_Variant_storage<false, _Types...>的析构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 constexpr  void _M_reset() {   if  (!_M_valid()) [[unlikely]]     return ;   std::__do_visit<void >([](auto && __this_mem) mutable      {       std::_Destroy(std::__addressof(__this_mem));     }, __variant_cast<_Types...>(*this ));   _M_index = static_cast <__index_type>(variant_npos); } _GLIBCXX20_CONSTEXPR ~_Variant_storage() { _M_reset(); } 
 
__do_visit即是gcc内std::visit的实现;_Destroy也是gcc内调用析构的方法,在17标准后调用std::destroy_at进行析构;std::__addressof同为gcc实现内的方法,可以视为std::addressof;所以这里的逻辑也比较清晰了,调用visit方法访问实际对象,泛型lambda内实参类型确定后利用addressof和destroy_at对指定类型析构。 
variant_npos为constexpr size_t固定为-1。
非成员函数 
std::visit 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 template <typename  _Visitor, typename ... _Variants>  constexpr  __detail::__variant::__visit_result_t <_Visitor, _Variants...>    visit (_Visitor&& __visitor, _Variants&&... __variants)     {    namespace  __variant = std::__detail::__variant;     if  ((__variant::__as(__variants).valueless_by_exception () || ...))       __throw_bad_variant_access("std::visit: variant is valueless" );     using  _Result_type       = __detail::__variant::__visit_result_t <_Visitor, _Variants...>;     using  _Tag = __detail::__variant::__deduce_visit_result<_Result_type>;     if  constexpr  (sizeof ...(_Variants) == 1 )         {        using  _Vp = decltype (__variant::__as(std::declval <_Variants>()...));         constexpr  bool  __visit_rettypes_match = __detail::__variant::           __check_visitor_results<_Visitor, _Vp>(             make_index_sequence<variant_size_v<remove_reference_t <_Vp>>>());         if  constexpr  (!__visit_rettypes_match)             {            static_assert (__visit_rettypes_match,                         "std::visit requires the visitor to have the same "                          "return type for all alternatives of a variant" );             return ;           }         else            return  std::__do_visit<_Tag>(             std::forward<_Visitor>(__visitor),             static_cast <_Vp>(__variants)...);       }     else        return  std::__do_visit<_Tag>(         std::forward<_Visitor>(__visitor),         __variant::__as(std::forward<_Variants>(__variants))...);   } 
 
这里先调用valueless_by_exception校验variant是否有值,再检查参数包_Variants内参数个数,个数为1时校验了_Visitor对于_Variants内所有成员返回值是否一致,再调用实现方法__do_visit,这里元编程内容很多,鉴于此篇篇幅就不一一解读了。再来看下__do_visit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93   template <typename  _Result_type, typename  _Visitor, typename ... _Variants>     constexpr  decltype (auto )     __do_visit (_Visitor&& __visitor, _Variants&&... __variants)       {             if  constexpr  (sizeof ...(_Variants) == 0 )           {          if  constexpr  (is_void_v<_Result_type>)              return  (void )  std::forward<_Visitor>(__visitor) ()  ;          else              return  std::forward<_Visitor>(__visitor)();         }       else          {           constexpr  size_t  __max = 11 ;                       using  _V0 = typename  _Nth_type<0 , _Variants...>::type;                      constexpr  auto  __n = variant_size_v<remove_reference_t <_V0>>;           if  constexpr  (sizeof ...(_Variants) > 1  || __n > __max)               {                             constexpr  auto & __vtable = __detail::__variant::__gen_vtable<                 _Result_type, _Visitor&&, _Variants&&...>::_S_vtable;               auto  __func_ptr = __vtable._M_access(__variants.index ()...);               return  (*__func_ptr)(std::forward<_Visitor>(__visitor),                                    std::forward<_Variants>(__variants)...);             }           else               {                              _V0& __v0                 = [](_V0& __v, ...) -> _V0& { return  __v; }(__variants...);               using  __detail::__variant::_Multi_array;               using  __detail::__variant::__gen_vtable_impl;               using  _Ma = _Multi_array<_Result_type (*)(_Visitor&&, _V0&&)>; #ifdef  _GLIBCXX_DEBUG # define  _GLIBCXX_VISIT_UNREACHABLE __builtin_trap #else  # define  _GLIBCXX_VISIT_UNREACHABLE __builtin_unreachable #endif  #define  _GLIBCXX_VISIT_CASE(N)                                                \   case N:                                                                \   {                                                                        \     if  constexpr (N < __n)                                                \       {                                                                        \         return __gen_vtable_impl<_Ma, index_sequence<N> >::                \           __visit_invoke(std::forward<_Visitor> (__visitor),                \                          std::forward<_V0> (__v0));                \       }                                                                        \     else  _GLIBCXX_VISIT_UNREACHABLE();                                        \   }               switch  (__v0. index ())                 {                   _GLIBCXX_VISIT_CASE(0 )                   _GLIBCXX_VISIT_CASE(1 )                   _GLIBCXX_VISIT_CASE(2 )                   _GLIBCXX_VISIT_CASE(3 )                   _GLIBCXX_VISIT_CASE(4 )                   _GLIBCXX_VISIT_CASE(5 )                   _GLIBCXX_VISIT_CASE(6 )                   _GLIBCXX_VISIT_CASE(7 )                   _GLIBCXX_VISIT_CASE(8 )                   _GLIBCXX_VISIT_CASE(9 )                   _GLIBCXX_VISIT_CASE(10 )                 case  variant_npos:                   using  __detail::__variant::__variant_idx_cookie;                   using  __detail::__variant::__variant_cookie;                   if  constexpr  (is_same_v<_Result_type, __variant_idx_cookie>                                  || is_same_v<_Result_type, __variant_cookie>)                      {                      using  _Npos = index_sequence<variant_npos>;                       return  __gen_vtable_impl<_Ma, _Npos>::                         __visit_invoke(std::forward<_Visitor>(__visitor),                                        std::forward<_V0>(__v0));                     }                   else                      _GLIBCXX_VISIT_UNREACHABLE();                 default :                   _GLIBCXX_VISIT_UNREACHABLE();                 } #undef  _GLIBCXX_VISIT_CASE #undef  _GLIBCXX_VISIT_UNREACHABLE             }         }     } 
 
元编程内容依旧非常多,也不一一解读了,大致逻辑就是在单个variant元素大于11个或者要访问的variant多于1个时使用跳表访问每个variant内容,否则就通过第一个variant的index进行访问。
std::holds_alternative 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 template <typename  _Tp, typename ... _Types>  constexpr  bool    holds_alternative (const  variant<_Types...>& __v)  noexcept     {    static_assert (__detail::__variant::__exactly_once<_Tp, _Types...>,                   "T must occur exactly once in alternatives" );     return  __v.index () == std::__find_uniq_type_in_pack<_Tp, _Types...>();   } template <typename  _Tp, typename ... _Types>  constexpr  size_t    __find_uniq_type_in_pack()   {     constexpr  size_t  __sz = sizeof ...(_Types);     constexpr  bool  __found[__sz] = { __is_same(_Tp, _Types) ... };     size_t  __n = __sz;     for  (size_t  __i = 0 ; __i < __sz; ++__i)       {         if  (__found[__i])           {             if  (__n < __sz)                return  __sz;             __n = __i;           }       }     return  __n;   } 
 
元编程的技巧,利用推导将variant模板参数包拿到再利用该参数包找到指定类型的index。
std::get 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 template <typename  _Tp, typename ... _Types>  constexpr  _Tp&   get (variant<_Types...>& __v)     {    static_assert (__detail::__variant::__exactly_once<_Tp, _Types...>,                   "T must occur exactly once in alternatives" );     constexpr  size_t  __n = std::__find_uniq_type_in_pack<_Tp, _Types...>();     return  std::get <__n>(__v);   } template <size_t  _Np, typename ... _Types>  constexpr  variant_alternative_t <_Np, variant<_Types...>>&   get (variant<_Types...>& __v)   {     static_assert (_Np < sizeof ...(_Types),                   "The index must be in [0, number of alternatives)" );     if  (__v.index () != _Np)       __throw_bad_variant_access(__v.valueless_by_exception ());     return  __detail::__variant::__get<_Np>(__v);   } template <size_t  _Np, typename  _Variant>  constexpr  decltype (auto )   __get (_Variant&& __v)  noexcept     { return  __variant::__get_n<_Np>(std::forward<_Variant>(__v)._M_u); }template <size_t  _Np, typename  _Union>  constexpr  decltype (auto )   __get_n (_Union&& __u)  noexcept     {    if  constexpr  (_Np == 0 )        return  std::forward<_Union>(__u) ._M_first._M_get ()  ;    else  if  constexpr  (_Np == 1 )       return  std::forward<_Union>(__u)._M_rest._M_first._M_get();     else  if  constexpr  (_Np == 2 )       return  std::forward<_Union>(__u)._M_rest._M_rest._M_first._M_get();     else        return  __variant::__get_n<_Np - 3 >(                std::forward<_Union>(__u)._M_rest._M_rest._M_rest);   } 
 
摘取了部分代码在上面,以std::get<ClassName>形式调用时利用上面holds_alternative提到的技巧找到index,最后递归找到实际index的_Uninitialized。