wrapper inside std::tuple

snippet.cpp
#include <iostream>
#include <memory>
#include <string>
 
struct A {
    std::string name;
};
struct B {};
struct C {};
struct D {};
 
template<typename V>
struct MyWrapperHelper {
    using type = std::shared_ptr<V>;
};
 
template<typename V>
using MyWrapperHelper_t = typename MyWrapperHelper<V>::type;
 
template<typename... ARGS>
struct MyWrapper {
    using type = std::tuple<MyWrapperHelper_t<ARGS>...>;
};
 
template<typename... ARGS>
using MyWrapper_t= typename MyWrapper<ARGS...>::type;
 
template<typename... ARGS>
class Container {
  public:
    MyWrapper_t<ARGS...> ms;
 
    template<typename V>
    std::shared_ptr<V> get() {
        return std::get<std::shared_ptr<V>>(ms);
    }
 
    template<typename V>
    void set(std::shared_ptr<V> v) {
        std::get<std::shared_ptr<V>>(ms) = v;
    }
};
 
int main() {
    std::cout << "Hello, World!" << std::endl;
 
    Container<A, B, C, D> c;
 
    {
        auto a_ptr = c.get<A>();
        if (a_ptr) {
            std::cout << "a.name: " << a_ptr->name << std::endl;
        } else {
            std::cout << "no a" << std::endl;
        }
    }
 
    auto new_a = std::make_shared<A>();
    new_a->name = "Alice";
    c.set(new_a);
 
    {
        auto a_ptr = c.get<A>();
        if (a_ptr) {
            std::cout << "a.name: " << a_ptr->name << std::endl;
        } else {
            std::cout << "no a" << std::endl;
        }
    }
 
    return 0;
}

type of MyWrapper_t<A, B, C, D> is std::tuple<std::shared_ptr<A>, std::shared_ptr<B>, std::shared_ptr<C>, std::shared_ptr<D>>