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

Reply via email to