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.