There are two steps to achieving this. The first is to identify the list of types used in the original std::variant
and the second is to construct a new std::variant
type with the original arguments plus the one to add.
Partial template specialization can be used to write a trait that will obtain the list of template types used in a given std::variant
:
#include <variant>
template<class T>
struct t_variant_cat;
template<class ... Old>
struct t_variant_cat<std::variant<Old...>> {
// Old is a parameter pack containing all of
// template arguments of the std::variant
};
Next we add another template argument that specifies the type to add and define an alias for this new type.
#include <variant>
template<class T, class New>
struct t_variant_cat;
template<class ... Old, class New>
struct t_variant_cat<std::variant<Old...>, New> {
using type = std::variant<Old..., New>;
};
typename t_variant_cat<my_variant, Class4>::type
should now yield std::variant<Class1, Class2, Class3, Class4>
. For convenience we can add a type alias to avoid having to write typename
and ::type
each time :
template<class Old, class New>
using t_variant_cat_t = typename t_variant_cat<Old, New>::type;
The usage would be :
#include <variant>
template<class T, class New>
struct t_variant_cat;
template<class ... Old, class New>
struct t_variant_cat<std::variant<Old...>, New> {
using type = std::variant<Old..., New>;
};
template<class Old, class New>
using t_variant_cat_t = typename t_variant_cat<Old, New>::type;
using old = std::variant<int, float>;
using extended = t_variant_cat_t<old, double>;
// Makes sure this actually works
static_assert(std::is_same_v<extended, std::variant<int, float, double>>,
"Something is wrong.");
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…