Search code examples
c++c++17variadic-templatesconstexpr

Create Link List from variadic arguments


I want to create a link list by taking the variable arguments given at compile time Description below:

I have a node something like given below:

template<typename T>
struct Node
{
    Node(const T& data, Node* next = nullptr ) : m_data(data),
                                                 m_next(next)
    {}
    
    T m_data;
    Node *m_next;
};

I have a function which takes variable number of arguments(variadic) like below, and should be able to create a link list from all the arguments and return head*(starting pointer) of the created list

template <class ... Ts>
constexpr Node* create(Ts && ... ts) {
    // should be able to create all nodes and return Head* for the given created list
    //return Head
}

main function would look like this

int main()
{
    auto *k = create(1,2,3,4,5,6);
    auto *n = create();  // should handle no arguments case
    auto *l = create(9,10,11,22,4567,90);
    
    return 0;

}

Solution

  • Do not make this over complicated and just use std::initializer_list. Use of variadic arguments here will be an overkill.

    Also Node should be an implementation detail of a list. So create a template class List which will be the only thing which uses Node.

    template<typename T>
    struct Node
    {
        T m_data;
        Node *m_next;
    };
    
    template<typename T>
    class List
    {
    public:
        List(std::initializer_list<T> ini)
        {
            for (const T& x : ini) {
               push_back(x);
            }
        }
    
        void push_back(const T& x);
        ....
    
    private:
       std::unique_ptr<Node> m_front;
       Node* m_back;
    };
    
    

    This is bad approach, and poor task for interview, but here it is:

    template<typename T>
    struct Node
    {
        constexpr explicit Node(const T& x) : m_data{x}
        {}
    
        T m_data;
        std::unique_ptr<Node> m_next;
    };
    
    template<typename T>
    using Node_t = Node<std::remove_reference_t<T>>;
    template<typename T>
    using NodePtr = std::unique_ptr<Node_t<T>>;
    
    template<typename T>
    constexpr NodePtr<T> create(T&& x)
    {
        return std::make_unique<Node_t<T>>(std::forward<T>(x));
    }
    
    template <typename T1, typename ... Ts>
    constexpr NodePtr<T1>
        create(T1&& x1, Ts && ...xi)
    {
        auto r = create(std::forward<T1>(x1));
        r->m_next = create(std::forward<Ts>(xi)...);
        return r;
    }
    

    https://godbolt.org/z/bbo5Tc