On Mon, Oct 15, 2018 at 08:13:19PM +0100, Jonathan Wakely wrote: > On Mon, 15 Oct 2018 at 20:08, Gabriel Paubert <paub...@iram.es> wrote: > > > > On Mon, Oct 15, 2018 at 08:11:42PM +0200, Florian Weimer wrote: > > > * Jonathan Wakely: > > > > > > > On Sun, 14 Oct 2018 at 20:46, Florian Weimer <f...@deneb.enyo.de> wrote: > > > >> > > > >> * Rasmus Villemoes: > > > >> > > > >> > This is something I've sometimes found myself wishing was supported. > > > >> > The > > > >> > idea being that one can say > > > >> > > > > >> > unsigned a[] = { [0] = 1, [1] = 3, [0] |= 4, ...} > > > >> > > > > >> > which would end up initializing a[0] to 5. As a somewhat realistic > > > >> > example, suppose one is trying to build a bitmap at compile time, but > > > >> > the bits to set are not really known in the sense that one can group > > > >> > those belonging to each index in a usual | expression. Something like > > > >> > > > > >> > #define _(e) [e / 8] |= 1 << (e % 8) > > > >> > const u8 error_bitmap[] = { _(EINVAL), _(ENAMETOOLONG), _(EBUSY), > > > >> > ... } > > > >> > > > >> I think it wouldn't be too hard to extend std::bitset with more > > > >> compile-time operations to support this, if that's what you need. > > > > > > > > It's already doable using C++17: > > > > > > I didn't doubt that, it's just that I'd expect to be able to use > > > std::bitset for this. > > > > > > > template<int... N> > > > > constexpr auto > > > > make_error_bitmap() > > > > { > > > > using std::uint8_t; > > > > using std::array; > > > > constexpr auto max_index = std::max_element({N...}) / 8; > > > > array<uint8_t, max_index+1> a; > > > > [[maybe_unused]] uint8_t sink[] = { a[N/8] |= (1 << (N%8)), ... }; > > > > return a; > > > > } > > > > > > > > constexpr uint8_t error_bitmap = make_error_bitmap<EINVAL, > > > > ENAMETOOLONG, EBUSY>(); > > > > > > > > (This won't compile in C++14 because std::array can't be modified in a > > > > constant expression until C++17). > > > > > > You wrote that without testing it? I'm impressed. It's really close. > > > > > > template<int... N> > > > constexpr auto > > > make_error_bitmap() > > > { > > > using std::uint8_t; > > > using std::array; > > > constexpr auto max_index = std::max({ N... }); > > > array<uint8_t, max_index+1> a{}; > > > [[maybe_unused]] uint8_t sink[] = { a[N/8] |= (1 << (N%8)) ... }; > > > return a; > > > } > > > > > > > Hmm, isn't the array roughly 8 times too large? > > Yes, it looks like I pasted the wrong version of the code, which is > why it had the stray comma that Florian corrected. The final version > of the code I actually wrote is: > > #include <array> > #include <algorithm> > #include <cstdint> > > template<int... N> > constexpr auto > make_error_bitmap() > { > using std::uint8_t; > using std::array; > constexpr auto max_index = std::max({N...}) / 8; > array<uint8_t, max_index+1> a{}; > [[maybe_unused]] uint8_t sink[] = { a[N/8] |= (1 << (N%8)) ... }; > return a; > } >
Looks like it no more wastes memory now. > constexpr auto error_bitmap = make_error_bitmap<EINVAL, ENAMETOOLONG, > EBUSY>(); > > (Note that max_index has the division by 8) > > > > > > IOW, shouldn't you declare "array<uint8_t, (max_index+7)/8> a{};" ? > > And this expression had an off-by-one error, sorry. > > > constexpr auto error_bitmap = make_error_bitmap<EINVAL, ENAMETOOLONG, > > > EBUSY>(); > > > > > > It seems to produce the intended bit pattern. > > > > Did you think of big-endian machines (just curious)? > > The code does what the OP asked for, I didn't try to figure out if > what it did made sense. Ok. Gabriel