Daniel McLaury
Daniel McLaury

Reputation: 4273

Can I initialize a `constexpr static` member outside the class?

I'm working with a variable-width communications format. The structs to handle it look something like this:

struct Header
{
  int msgType = -1, len;

  Header() { len = sizeof(*this); }
};

struct A : public Header
{
  int x; char y;

  A() { msgType = 1; len = sizeof(*this); }
};

// Further structs B, C, ... declared along the same lines

I would like to have a constexpr static member Header::MAX_SIZE which gives the max size of any of these derived classes, e.g. so I can allocate a buffer which is guaranteed to hold any such packet. So I'd like to do something like

struct Header
{
  int msgType = -1, len;

  constexpr static std::size_t MAX_SIZE;

  Header() { len = sizeof(*this); }
};

// ... declaration of subclasses ...

inline Header::MAX_SIZE = std::max({ sizeof(A), sizeof(B), sizeof(C) });

I need the definition to come outside of the class because it depends on sizeof(A), etc., which in turn depend on the definition of Header.

It seems like this sort of thing should be unobjectionable: I'm giving the definition of the member in the same source file, and it can be computed at compile time. But I haven't found any way to tell the compiler to actually do this.

Upvotes: 10

Views: 1584

Answers (1)

Davis Herring
Davis Herring

Reputation: 39818

constexpr goes on the initializing declaration of a variable, so just put it outside the class:

struct Header
{
  int msgType = -1, len;

  static const std::size_t MAX_SIZE;

  Header() { len = sizeof(*this); }
};

// ... declaration of subclasses ...

inline constexpr std::size_t Header::MAX_SIZE = std::max({ sizeof(A), sizeof(B), sizeof(C) });

Note that the implicit const must be spelled out in the declaration. The definition should go in the same header to avoid any translation unit seeing the declaration but not the inline, which is not allowed.

Upvotes: 12

Related Questions