I have been looking at how the initializer_list
is implemented so I found section 18.9 of the standard and found a simple enough looking interface. I thought it wou
This answer is not entirely accurate. It is possible to create a fully functional std::initializer_list
- it just needs to meet the specific requirements of the target compiler.
For GCC and clang that requirement is a private ctor. Here is the libc++ implementation (which also happens to work fine with GCC 8.3):
template<class _Ep>
class initializer_list
{
const _Ep* __begin_;
size_t __size_;
inline
constexpr
initializer_list(const _Ep* __b, size_t __s) noexcept
: __begin_(__b),
__size_(__s)
{}
public:
typedef _Ep value_type;
typedef const _Ep& reference;
typedef const _Ep& const_reference;
typedef size_t size_type;
typedef const _Ep* iterator;
typedef const _Ep* const_iterator;
inline
constexpr
initializer_list() noexcept : __begin_(nullptr), __size_(0) {}
inline
constexpr
size_t size() const noexcept {return __size_;}
inline
constexpr
const _Ep* begin() const noexcept {return __begin_;}
inline
constexpr
const _Ep* end() const noexcept {return __begin_ + __size_;}
};
template<class _Ep>
inline
constexpr
const _Ep*
begin(initializer_list<_Ep> __il) noexcept
{
return __il.begin();
}
template<class _Ep>
inline
constexpr
const _Ep*
end(initializer_list<_Ep> __il) noexcept
{
return __il.end();
}
The name is important because the standard says it is. The standard needs some way for you to be able to say, "this constructor can be passed a braced-init-list containing a sequence values of the type T". That way was given the name "std::initializer_list
".
You cannot make a class that has all of the language properties of initializer_list
. You can make one that satisfies the conditions of the type specified by section 18.9 of the standard. But you'll notice that the only constructor specified there is a default constructor. The only way to create an initializer_list
with actual elements relies on the compiler, not user-land code.
So you can't replicate everything about initializer_list
. Just as you can't replicate std::type_info
. The C++ standard library is not optional.
I've found this post when I had issues implementing initializer_list myself and found it very useful to write my own version that would compile on msvc, gcc, avr-gcc and clang. This question may be old but I would like to share my solution in hope that others find it useful:
#include <stddef.h>
namespace std
{
#if defined(__GNUC__)
// Copyright (C) 2008-2020 Free Software Foundation, Inc.
// Copyright (C) 2020 Daniel Rossinsky <danielrossinsky@gmail.com>
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
//
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
template<typename T>
class initializer_list
{
public:
using value_type = T;
using reference = const T&;
using const_reference = const T&;
using size_type = size_t;
using iterator = const T*;
using const_iterator = const T*;
private:
iterator m_array;
size_type m_len;
// The compiler can call a private constructor.
constexpr initializer_list(const_iterator itr, size_type st)
: m_array(itr), m_len(st) { }
public:
constexpr 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(); }
};
#elif defined(__clang__)
// Copyright (c) 2019 Chandler Carruth <https://github.com/chandlerc>
// Copyright (c) 2018 Louis Dionne <https://github.com/ldionne>
// Copyright (c) 2017 Eric <https://github.com/EricWF>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---- LLVM Exceptions to the Apache 2.0 License ----
//
// As an exception, if, as a result of your compiling your source code, portions
// of this Software are embedded into an Object form of such source code, you
// may redistribute such embedded portions in such Object form without complying
// with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
//
// In addition, if you combine or link compiled forms of this Software with
// software that is licensed under the GPLv2 ("Combined Software") and if a
// court of competent jurisdiction determines that the patent provision (Section
// 3), the indemnity provision (Section 9) or other Section of the License
// conflicts with the conditions of the GPLv2, you may retroactively and
// prospectively choose to deem waived or otherwise exclude such Section(s) of
// the License, but only in their entirety and only with respect to the Combined
// Software.
template<typename T>
class initializer_list
{
private:
const T* m_first;
const T* m_last;
public:
using value_type = T;
using reference = const T&;
using const_reference = const T&;
using size_type = size_t;
using iterator = const T*;
using const_iterator = const T*;
initializer_list() noexcept : m_first(nullptr), m_last(nullptr) {}
// Number of elements.
size_t size() const noexcept { return m_last - m_first; }
// First element.
const T* begin() const noexcept { return m_first; }
// One past the last element.
const T* end() const noexcept { return m_last; }
};
#elif defined(_MSC_VER)
// Copyright (c) Microsoft Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ---- LLVM Exceptions to the Apache 2.0 License ----
//
// As an exception, if, as a result of your compiling your source code, portions
// of this Software are embedded into an Object form of such source code, you
// may redistribute such embedded portions in such Object form without complying
// with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
//
// In addition, if you combine or link compiled forms of this Software with
// software that is licensed under the GPLv2 ("Combined Software") and if a
// court of competent jurisdiction determines that the patent provision (Section
// 3), the indemnity provision (Section 9) or other Section of the License
// conflicts with the conditions of the GPLv2, you may retroactively and
// prospectively choose to deem waived or otherwise exclude such Section(s) of
// the License, but only in their entirety and only with respect to the Combined
// Software.
template<typename T>
class initializer_list
{
public:
using value_type = T;
using reference = const T&;
using const_reference = const T&;
using size_type = size_t;
using iterator = const T*;
using const_iterator = const T*;
constexpr initializer_list() noexcept : m_first(nullptr), m_last(nullptr) {}
constexpr initializer_list(const T* first, const T* last) noexcept
: m_first(first), m_last(last) {}
// First element.
constexpr const T* begin() const noexcept { return m_first; }
// One past the last element.
constexpr const T* end() const noexcept { return m_last; }
// Number of elements.
constexpr size_t size() const noexcept
{
return static_cast<size_t>(m_last - m_first);
}
private:
const T* m_first;
const T* m_last;
};
#else
#error "Initializer_list is not supported for this compiler"
#endif
template<typename T>
constexpr const T* begin(initializer_list<T> il) noexcept
{
return il.begin();
}
template<typename T>
constexpr const T* end(initializer_list<T> il) noexcept
{
return il.end();
}
}
NOTE:
I added copyright notices with license preambles of each implementation directly above the implementation in order to give credit to whom credit is due for the code and promote fair use.
IANAL:
The only copyright that was included properly was from gcc, the msvc version lacks a year and clang (llvm) should have copyright assigned to the contributors which I did manually. However, Im not an expert and may have missed/misunderstood the way I am allowed to share the code. If so, please let me know and I will apply changes immediately.
Also, as far as I understand Apache-2.0 is compatible with GPLv3 in only one direction. you can sublicense my entire code under GPLv3 but not under Apache-2.0
PROOF OF WORK:
The example I used to show proof my version works is taken from learncpp: