c++stlinitializer-list

Using an initializer list to init a vector


I can not figure out why it does not allow me to directly initialize a vector using the following syntax:

stl::vector<int> v{1, 2, 3};

I have implemented from scratch both the vector and the initializer list classes.

The vector constructor (there is also a default constructor which just sets everything to 0):

vector(initializer_list<T> init) : m_capacity(init.size()), m_size(m_capacity), m_data(nullptr)
{
 this->m_data = (T *)malloc(m_size * sizeof(T));

 if (this->m_data == nullptr)
      throw "malloc: Couldn't allocate memory!\n";

 memcpy(m_data, init.begin(), m_size * sizeof(T));
}

This is my initializer_list class:

    template <typename T> class initializer_list 
    {
    public:
        typedef const T* const_iterator;
        typedef       T* iterator;

    private:
        iterator m_begin;
        size_t   m_size;

        constexpr initializer_list(const_iterator it, size_t size) noexcept : m_begin(it), m_size(size) { }

    public:
        constexpr initializer_list() noexcept : m_begin(nullptr), m_size(0) { }

        constexpr const_iterator begin() const { return m_begin; }

        constexpr const_iterator begin(initializer_list<T> init) noexcept { return init.begin(); }

        constexpr const_iterator end() const { return m_begin + m_size; }

        constexpr const_iterator end(initializer_list<T> init) noexcept { return init.end(); }

        constexpr size_t size() const { return m_size; }
    };

I created a separate constructor in the vector class which takes a initializer list as parameter. However I get the following error:

no instance of constructor "stl::vector<T>::vector [with T=int]" matches the argument list


Solution

  • std::initializer_list is a magic type that can't be implemented by user code.

    The special behavior of overload resolution and braced initializer lists work only specifically for that magic std::initializer_list type.

    You can't define your own initializer_list and hope for it to work like std::initializer_list.

    You also can't make the stl::vector<int> v{1, 2, 3}; syntax work without using std::intializer_list. There is no way around using it. The syntax can't be achieved in any other way.

    The standard library has a lot of these magic types and functions btw. Some of them are simply unimplementable by user code and need to rely on compiler builtins instead. But some, such as std::initializer_list, also have special meaning to the compiler itself and couldn't even be replicated using the compiler's builtins.