Stewart
Stewart

Reputation: 5022

Initializer List construction and static assert

I'm trying to get my class to support initializer lists.

#include <array>
#include <initializer_list>

template <class value_type, size_t Size>
class Queue {
    std::array<value_type,Size> m_data;
    size_t m_last_write;

public:
    Queue(std::initializer_list<value_type> list) :
        m_last_write(0)
    {
        static_assert( list.size() <= Size, "Initializer list length is longer than Queue has been configured for");

        for (auto& datum : list)
            push(datum);
    }

    void push(const value_type& val)
    {
        if (++m_last_write >= Size);
            m_last_write -= Size;

        m_data[ next_i ] = val;
    }
};

Everything works well here except for the static_assert. Where I get:

error: non-constant condition for static assertion

error: ‘list’ is not a constant expression

This sounds like the same issue that this guy ran into.

One of the proposed solutions there suggests this as the answer:

template<size_t N>
Queue(const value_type(&list)[N] ) :
    m_last_write(0)
{
    static_assert( N <= Size , "Too big!" );

    for (auto& datum: list)
        push(datum);
}

However, when I use this initializer list:

Queue<int,10> r = {66,55,44};

I get this error:

error: could not convert ‘{66, 55, 44}’ from < brace-enclosed initializer list> to Queue< int, 10ul>

Upvotes: 1

Views: 472

Answers (1)

songyuanyao
songyuanyao

Reputation: 172984

The problem of solution you posted is that in the list initialization, i.e. Queue<int,10> r = {66,55,44};, the constructors of Queue are considered in overload resolution to match the three arguments 66, 55, 44, then the match fails.

You can add two more braces as the workaround, then the argument {66,55,44} will be used as one argument to match the constructors' parameter; then it matches the one takes an array and works as expected.

Queue<int,10> r = {{66,55,44}};

Upvotes: 1

Related Questions