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 <[email protected]>
//
// 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:
- Arduino 1.8.9
- x86 msvc v19.28
- x86-64 clang (trunk)
- x86-64 gcc (trunk)
std::initializer_list
class is very much compiler specific. – Marshynew
operator a language feature? It depends onstd::bad_alloc
. What aboutdynamic_cast
, which depends onstd::bad_cast
?typeid
operator producing an object of typestd::type_info
? There's a whole section in the standard called "Language support library". – AnacreonArrayPrinter<int> ap{ {1,2,3} };
it works as expected: live example – Lightweighttemplate <typename... TT> InitializerList(TT&&... pp) : storage{pp...} {}
is just forwarding thestd::initializer_list
to the vector. – Margitstd::initializer_list
is created in my example. The{1,2,3}
which appears there (is a braced-init-list and) is used to construct aMyNamespace::InitializerList<int>
by calling the template ctor in the same way as inArrayPrinter<int> ap( MyNamespace::InitializerList<int>(1,2,3) );
– Lightweightinitializer_list
? How is a compiler meant to guess what you want it to do with an arbitrary type you create? More to the point, where is the definition of that type? This seems very incomplete. Also, the Coliru link claiming to make this "work as expected" doesn't really make anything work, since it just implements the user-defined faux-initialisation-list by using avector
, which is a waste of dynamic allocation and only works because it has a ctor taking the realinitializer_list
anyway... – Broadbent