c++templatesvariantcompile-time

Building a std::variant of pointers of types in the alternatives of another std::variant


I'm given a std::variant of several types. I would like to write a trait that gives another std::variant of the pointer of the types of the first.

using MyVariant = std::variant<int, float>;

using MyVariantOfPointers = pointer_of_v<MyVariant>;

such that MyVariantOfPointer is std::variant<int*, float*>. I tried to play with std::variant_size_v and std::variant_alternative_t but I do not know how to build the new type recursively.


Solution

  • You can use partial specialization to write a trait to solve this.

    // General case
    template<class T>
    struct VariantToPtrVariant;
    
    // Partial specialization when used with std::variant
    // Extracts the template arguments from the `std::variant` and 
    //  produces a new `std::variant` with those types, with an added `*`
    template<class ... T>
    struct VariantToPtrVariant<std::variant<T...>> {
        using type = std::variant<T*...>;
    };
    
    // Helper variable template
    template<class T>
    using VariantToPtrVariant_t = typename VariantToPtrVariant<T>::type;
    

    Usage :

    using MyVariant = std::variant<int, float>;
    using MyVariantOfPointers = VariantToPtrVariant_t<MyVariant>;
    

    Complete example (https://godbolt.org/z/qaTxo4nzc) :

    #include <type_traits>
    #include <variant>
    
    template<class T>
    struct VariantToPtrVariant;
    
    template<class ... T>
    struct VariantToPtrVariant<std::variant<T...>> {
        using type = std::variant<T*...>;
    };
    
    template<class T>
    using VariantToPtrVariant_t = typename VariantToPtrVariant<T>::type;
    
    using MyVariant = std::variant<int, float>;
    using MyVariantOfPointers = VariantToPtrVariant_t<MyVariant>;
    
    static_assert(std::is_same_v<MyVariantOfPointers, std::variant<int*, float*>>);