1

I am trying to do a dynamic allocation of template. Below is my code. What would be the problem? I thought the constructor of class AAA might be a problem, but I have no idea how to deal with it.

class AAA {
private:
    int id;
public:
    AAA(int s):id(s) {}
};

template<typename T>
class Buffer {
private:
    T *buffer;
    int capacity;

public:
    Buffer(int capacity): capacity(capacity){
        buffer = new T[capacity];
    }
};

int main {
    Buffer<AAA> buffer(3);
}

This generates the below error.

script.cpp:55:18: error: no matching function for call to ‘AAA::AAA()
         buffer = new T[capacity];
                  ^~~~~~~~~~~~~~~`
leeway00
  • 87
  • 1
  • 1
  • 6

1 Answers1

2

The error message is telling you that the class AAA does not have a default constructor. That is required because new will default-construct each element in buffer.

The only constructor AAA provides right now needs an integer parameter that's used to construct the object with an ID.

It's up to you what you choose to do here. By far the simplest fix is to relax that constructor and provide a default id if none was specified. This conveniently gives you a default constructor by magic.

class AAA {
private:
    int id;
public:
    AAA(int s = 0) : id(s) {}
};

As a side-node, your main definition is wrong. It needs parentheses:

int main()
{
    Buffer<AAA> buffer(3);
}

Don't forget about The Rule of Three for your Buffer class. Right now, it leaks memory and is unsafe to copy. Consider using std::vector instead of allocating data yourself. At the very least, avoid storing raw pointers: use std::unique_ptr<T[]> instead.

As pointed out by Davis Herring in the comments, your class might intentionally have no valid default / empty state. In that case, std::vector is really what you need. Here's your Buffer class adjusted to reserve vector storage instead.

template<typename T>
class Buffer {
private:
    std::vector<T> buffer;

public:
    Buffer(int capacity)
    {
        buffer.reserve(capacity);
    }

    void Add(const T & val)
    {
        buffer.push_back(val);
    }

    void Add(T && val)
    {
        buffer.push_back(std::move(val));
    }
};

Note that the vector is still empty, but has reserved storage. You will need to create method(s) in the Buffer class to append stuff to it, as suggested in the example.

paddy
  • 60,864
  • 6
  • 61
  • 103
  • 3
    Using `std::vector` will also avoid the need for the default constructor, which is good if there really is no appropriate "empty" state for your class. – Davis Herring Apr 14 '23 at 04:28
  • It does appear that OP is trying to create something similar to `std::vector`, but that can be a challenge. They would need to allocate an uninitialized buffer using a POD type like `char`, ensure the alignment is correct, and use placement-new / placement-delete when adding data. While a fun exercise, it's a major hassle. It's fine to just encapsulate the vector in the `Buffer` class. That allows you to limit the operations available by providing your own interface, and/or allow for future changes to the internal representation of `Buffer` without affecting code that uses it already. – paddy Apr 14 '23 at 04:34