I was implementing the circular array data structure whose code looks like this:
struct CircularArrayException : public std::exception {
std::string msg;
CircularArrayException(const std::string arg_msg)
: msg{"CircularArrayException: " + arg_msg} {}
const char * what () const throw () {
return msg.c_str();
}
};
template <typename T>
class CircularArray {
public:
const size_t array_size;
std::unique_ptr<T> uptr_arr;
size_t occupied_size = 0;
int front_idx = -1;
int back_idx = -1;
CircularArray(const CircularArray& ca) = delete;
CircularArray& operator=(const CircularArray& ca) = delete;
CircularArray(
const size_t arg_array_size
): array_size{arg_array_size} {
uptr_arr = std::make_unique<T>(array_size);
};
};
After the implementation I tested the implementation with CircularArray<char> and it works fine.
But, then I realized that we use std::make_unique<char[]>(num_elements) to declare a unique_ptr to an array as opposed to std::make_unique<char>(num_elements). But, even then the code seems to work fine. I looked the documentation of std::make_unique here and couldn't understand the explanation of the (2)nd signature. Can anyone help me out to understand the difference and why my code works?
Here is the what is written on cppreference for the (2) signature:
template< class T >
unique_ptr<T> make_unique( std::size_t size );
(2) (since C++14) (only for array types with unknown bound)
Constructs an array of unknown bound T. This overload participates in overload resolution only if T is an array of unknown bound. The function is equivalent to: unique_ptr<T>(new typename std::remove_extent<T>::type[size]())
Here is the goldbolt link: https://godbolt.org/z/K9h3qTeTW