anton_rh
anton_rh

Reputation: 9213

Is it legal to derive from std::initializer_list?

Can I use std::initializer_list list as a base class?

template <typename T>
struct il : std::initializer_list<T>
{
    using base = std::initializer_list<T>;

    il(base list): base(list) {}

    const T &operator[](size_t i) const
        { return *(base::begin()+i); }
};

void print2(il<int> list)
{
    for (size_t i = 0; i < list.size(); i += 2)
        { std::cerr << list[i] << "; "; }

    std::cerr << std::endl;
}

int main()
{
    print2({0, 1, 2, 3, 4, 5, 6});
}

// The output: 0; 2; 4; 6; 

The code above works in both GCC and Clang. But is it actually valid?

The cppreference.com defines std::initializer_list as follows:

template< class T >
class initializer_list;

But does this mean that std::initializer_list is an ordinary class like any other? I thought it is kind of special object in C++.

Upvotes: 1

Views: 64

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70347

The best reference to this I can find in the standard is §16.4.5.1

The following subclauses specify constraints on ... [the program's] use of standard library classes as base classes

And then later in §16.4.5.5

Virtual member function signatures defined for a base class in the C++ standard library may be overridden in a derived class defined in the program

Which would seem to imply that it's fair game to subclass stdlib classes.

Of course, using those subclasses as an actual std::initializer_list is going to be difficult. Every use case I can think of in C++ for std::initializer_list takes one by value, so your subclass is going to get sliced before it ever gets passed to most constructors.

Upvotes: 1

Related Questions