Search code examples
c++templatesinitializer-liststdinitializerlist

Cannot convert initializer_list to class<int>


I am trying to initialize_list for a class template. I am fairly a newbie and have had some trouble with this. Error on main()

#include <iostream>
#include <initializer_list>
#include <stdexcept>

template <class T>
class Storage
{
private:
    int nrOfEl{ 0 };
    T *m_array{};
public:
//...
    Storage(std::initializer_list<T>& list)
        : Storage( static_cast<int>(list.size()) )
    {
        int count{ 0 };
        for (auto& element : list)
        {
            m_array[count] = element;
            ++count;
        }
    }

    ~Storage()
    {
        std::cout << "\nCalling ~Storage()\n";
        delete[] m_array;
    }

    T& operator[](const int &index)
    {
        if (index >= nrOfEl || index < 0)
            throw std::out_of_range("OUT OF BOUNDS");
        return *m_array[index];
    }

    Storage& operator=(std::initializer_list<T>& list)
    {
        int length{ static_cast<int>(list.size()) };
        if (length != nrOfEl)
        {
            delete[] m_array;
            nrOfEl = length;
            m_array = new int[length];
        }

        int count = 0;
        for (int element : list)
        {
            m_array[count] = element;
            ++count;
        }

        return *this;
    }
//...
};

int main()
{
    Storage<int> ints { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
        //error here
    return 0;
}

error C2440: 'initializing': cannot convert from 'initializer list' to 'Storage'

note: No constructor could take the source type, or constructor overload resolution was ambiguous


Solution

  • In main(), your initializer list is constructed as an r-value, so pass-by-reference will fail. Passing by const-reference, however, will work. You should allow the constructor to accept const-reference lists:

    Storage(const std::initializer_list<T>& list)
    //      ^^^^^
        : Storage( static_cast<int>(list.size()) )
    {
        int count{ 0 }; 
        for (const auto& element : list)    // const here too
        {
            m_array[count] = element;
            ++count;
        }
    }
    

    You should also change the parameter likewise with operator=.