Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

the implemention of std::initializer_list

Tags:

c++

c++11

stl

I copied the code from header file initializer_list and renamed the class name to my_initializer_list

template<class _E>
    class my_initializer_list
    {
    public:
      typedef _E        value_type;
      typedef const _E&     reference;
      typedef const _E&     const_reference;
      typedef size_t        size_type;
      typedef const _E*     iterator;
      typedef const _E*     const_iterator;

    private:
      iterator          _M_array;
      size_type         _M_len;

      // The compiler can call a private constructor.
      constexpr my_initializer_list(const_iterator __a, size_type __l)
      : _M_array(__a), _M_len(__l) { }

    public:
      constexpr my_initializer_list() noexcept
      : _M_array(0), _M_len(0) { }

      // Number of elements.
      constexpr size_type
      size() const noexcept { return _M_len; }

      // First element.
      constexpr const_iterator
      begin() const noexcept { return _M_array; }

      // One past the last element.
      constexpr const_iterator
      end() const noexcept { return begin() + size(); }
    };

and the code:

int main()
{
    my_initializer_list<int> foo = {1,2,3};

    return 0;
}

and get the error:

could not convert '{1, 2, 3}' from '<brace-enclosed initializer list>' to 'my_initializer_list<int>'

My question : How STL implement the initializer_list class?

like image 218
qianyang Avatar asked Nov 19 '25 03:11

qianyang


1 Answers

It works withstd::initializer_list because even though std::initializer_list is a class, it is not a regular class. It is a very very special class, in the sense that when you write auto x = {1,2,3}; the compiler is going to infer x to be std::initializer_list<int> and initialize it accordingly. The compiler does black magic here to carry out the type-inference and initialization. It is not only library-feature. It is a core-langugage feature as well.

If you're going to use my_initializer_list instead, then its constructor needs to accept std::initializer_list so that the compiler can do the black magic for you.

Note that {1,2,3} is a type-less expression — well, to be pedantic, it is not even an expression; only in some special cases, it can be used to initialize objects using some special rules. For example, see this:

auto items = {1,2,3}; //OK: items is inferred to be std::initializer_list<int>
                      //must #include <initializer_list>

However, in case of templates, the rule is different:

 template<typename T>
 void f(T const & items); 

 f({1,2,3}); //ILL-FORMED: T cannot be deduced to be
             //std::initializer_list<int> or anything else
             //even if you use #include <initializer_list>

 f(std::initializer_list<int>{1,2,3}); //OK: #include <initializer_list>

 f(std::vector<int>{1,2,3}); //OK: #include <vector>
                             //because std::vector accepts std::initializer_list<T>

Hope that helps.

like image 116
Nawaz Avatar answered Nov 20 '25 18:11

Nawaz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!