Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Initialize POD base class with constexpr constructor

59 views
Skip to first unread message

Marcel Mueller

unread,
Apr 27, 2016, 5:08:00 PM4/27/16
to
I have a POD structure that should be initialized at compile time.
For this purpose I created a derived type with a constructor. This seems
to be impossible with C++11. At least I did not find a trick so far.
I get an error "constexpr constructor does not have an empty body".

The base type must be POD because it is also part of unions.
Performance and memory footprint count because of ARMV7.
Almost everything is polymorphic here but I need to avoid runtime
polymorphic types (i.e. vtables) because of the large overhead for ten
thousands of small instances and first of all the costly static
initialization code.

Any hints?


#include <inttypes.h>

// Pack or unpack
struct rPUp
{ uint8_t Mode;
bool isUnpack() const { return (Mode & 0x80) != 0; }
// other member functions...
};

enum Pack : uint8_t
{ P_16a
, P_16b
//...
};
enum Unpack : uint8_t
{ U_8a
//...
};

// Helper class to keep rPUp a POD and init dispatch table
struct mkPUp : rPUp
{ constexpr mkPUp(Pack pack) { Mode = pack; }
constexpr mkPUp(Unpack unpack) { Mode = unpack|0x80; }
constexpr operator int() const { return Mode; }
};

class Parser
{
struct opExtEntry
{ char Name[16];
// Parser function to call, receives an arbitrary argument.
void (Parser::*Func)(int);
// Argument to the parser function
int Arg;
};

void addPUp(int param)
{ //...
}
void addIf(int param)
{ //...
}
// other parser functions

static const opExtEntry extMap[];
};

enum Cond
{ C_NZ
//...
};

// Dispatch table
const Parser::opExtEntry Parser::extMap[] =
{ { "ifnz", &Parser::addIf, C_NZ }
, { "pack16a", &Parser::addPUp, mkPUp(P_16a) }
, { "pack16b", &Parser::addPUp, mkPUp(P_16b) }
, { "unpack8a", &Parser::addPUp, mkPUp(U_8a) }
//...
};

Ian Collins

unread,
Apr 27, 2016, 5:45:25 PM4/27/16
to
On 04/28/16 09:07, Marcel Mueller wrote:
> I have a POD structure that should be initialized at compile time.
> For this purpose I created a derived type with a constructor. This seems
> to be impossible with C++11. At least I did not find a trick so far.
> I get an error "constexpr constructor does not have an empty body".
>
> The base type must be POD because it is also part of unions.

Do you need pod, or just standard layout?

If the latter, you could skip the helper and give rPUp constexpr
constructors, something like

enum Pack : uint8_t
{ P_16a
, P_16b
//...
};
enum Unpack : uint8_t
{ U_8a = 0x80
//...
};

struct rPUp
{
uint8_t Mode;

constexpr rPUp(Pack pack) : Mode{ pack } {}
constexpr rPUp(Unpack unpack): Mode {unpack|0x80} {}

constexpr bool isUnpack() const { return (Mode & 0x80) != 0; }
constexpr operator int() const { return Mode; }

// other member functions...
};

--
Ian Collins

Marcel Mueller

unread,
Apr 29, 2016, 1:47:15 AM4/29/16
to
On 27.04.16 23.45, Ian Collins wrote:
>> The base type must be POD because it is also part of unions.
>
> Do you need pod, or just standard layout?
>
> If the latter, you could skip the helper and give rPUp constexpr
> constructors, something like

AFAIR members of a union must not contain constructors.
This seems not to be true, it compiles also when rPUp has a constructor.

I wonder how the compiler can handle this. Which constructor should be
invoked when some of the union members have a constructor?
In fact it works somehow. - Puzzled...


Marcel

Öö Tiib

unread,
Apr 29, 2016, 2:01:39 AM4/29/16
to
Unions in C++ have changed quite a lot with C++11. See Stroustrup's C++11
FAQ about unions for starters:
http://www.stroustrup.com/C++11FAQ.html#unions
0 new messages