How do I create a self-contained container class which can handle arbitrary types as a template in C++

61 Views Asked by At

So, while learning about templates, I thought of creating a container class whose constructor upon being called allocates memory using the new operator and then deallocates it when the destructor is called.

template<typename T> 
class container{
    public:
        container(size_t n) : m_size(n) , m_data(new T[n])
          {std::cout << "constructor called for n = " << n << endl; };
        container(size_t n, T&& t) : m_size(n), m_data(new T[n]) {
            std::cout << "constructor called for n = " << n << endl;
            for(size_t i = 0 ; i < n ; i++) {
                m_data[i] = t;
            }
        }
        ~container() {operator delete[]((m_data)); std::cout << "destructor called for n = " << m_size << endl;};
    private:
        T* m_data;
        size_t m_size;
};

This works fine for something like

container<int> c(10,2);

Then I thought that as the argument to the template can be anything, why not do something like

container<container<int>> v(3,container<int>(2));

To my surprise, this gives a compilation error which is hard for me to understand.


g++-13 variadic.cpp -o v                                                                                                                                  ✔  base   18:45:09  
variadic.cpp: In instantiation of 'container<T>::container(size_t, T&&) [with T = container<int>; size_t = long unsigned int]':
variadic.cpp:24:50:   required from here
variadic.cpp:10:64: error: no matching function for call to 'container<int>::container()'
   10 |                 container(size_t n, T&& t) : m_size(n), m_data(new T[n]) {
      |                                                                ^~~~~~~~
variadic.cpp:10:17: note: candidate: 'container<T>::container(size_t, T&&) [with T = int; size_t = long unsigned int]'
   10 |                 container(size_t n, T&& t) : m_size(n), m_data(new T[n]) {
      |                 ^~~~~~~~~
variadic.cpp:10:17: note:   candidate expects 2 arguments, 0 provided
variadic.cpp:9:17: note: candidate: 'container<T>::container(size_t) [with T = int; size_t = long unsigned int]'
    9 |                 container(size_t n) : m_size(n) , m_data(new T[n]){std::cout << "constructor called for n = " << n << endl; };
      |                 ^~~~~~~~~
variadic.cpp:9:17: note:   candidate expects 1 argument, 0 provided
variadic.cpp:7:7: note: candidate: 'constexpr container<int>::container(const container<int>&)'
    7 | class container{
      |       ^~~~~~~~~

First I thought that the creators of the STL vector must have faced this exact problem, so I tried to allocate naked memory using n*sizeof(T) and doing unsafe stuff like casting which I didn't feel comfortable about. Without any surprises, I got a segmentation fault due to double free.

0

There are 0 best solutions below