Search code examples
c++templatesmetadata

Make new instance of the template class of a c++ object


So if I have

template <class T>
class Object {
// stuff
};

and I receive an instance of object in a function I want to call the constructor of class T.

void foo(Object object) {
 auto newT = object::T();
}

Is this possible?


Solution

  • Typically the best solution is to template the inner type:

    template <class T>
    void foo(Object<T> object) {
        T newT;
    }
    

    However, sometimes (with more meta-programming) this sort of solution will be more verbose than the alternatives:


    Option 1: store the template variable in the Object class:

    template <class T>
    class Object {
        // stuff
    public:
        using inner_type = T;
    };
    

    Then you can access the template type like so:

    template <class Obj>
    void foo(Obj object) {
        typename Obj::inner_type newT;
    }
    

    Option 2: make a type trait (no need to add inner_type to Object):

    template <class T>
    struct tag {
        using type = T;
    };
    
    template <class>
    struct inner;
    
    template <template <class> class S, class T>
    struct inner <S<T>> : tag<T> {};
    
    template <typename T>
    using inner_t = typename inner<T>::type;
    

    Which you can then use like so:

    template <class Obj>
    void foo(Obj object) {
        inner_t<Obj> newT;
    }
    

    It's probably best to generalise inner_type to take the first inner argument so that it could handle template types with more arguments, like std::vector (second argument has a default):

    template <class>
    struct front;
    
    template <template <class, class...> class R, class S, class ... Ts>
    struct front <R<S, Ts...>> : tag<S> {};
    
    template <typename T>
    using front_t = typename front<T>::type;
    

    Demo