    #include <utility>
    
    // empty declaration with variable number of arguments
    template<typename...>
    struct hnode;
    
    // specialization for 1 template argument
    template<typename T>
    struct hnode<T> {
        T data;
        std::nullptr_t next;
    };
    
    // specialization for multiple template arguments
    template<typename T, typename... Rest>
    struct hnode<T, Rest...> {
        T data;
        hnode<Rest...>* next;
    };
    
    template<typename T>
    hnode<T> hcons(T&& val, std::nullptr_t) {
        return { std::forward<T>(val), nullptr };
    }
    
    template<typename T, typename... Rest>
    hnode<T, Rest...> hcons(T&& val, hnode<Rest...>& next) {
        return { std::forward<T>(val), &next };
    }
    
    int main() {
        hnode<int> three = hcons(1, nullptr);
        auto two = hcons("hi", three);
    }