H Bellamy
H Bellamy

Reputation: 22705

constexpr constructor referring to base class varies between compilers

The following code compiles with Clang (3.9.1 tested) and GCC (6.3 tested), as shown in this link: https://godbolt.org/g/kO1nBa. However, MSVC (19.00.24215.1 tested) fails to compile it:

struct ValueWitnessTable {
  int size;
};

struct ExtraInhabitantsValueWitnessTable : ValueWitnessTable {
  constexpr ExtraInhabitantsValueWitnessTable(const ValueWitnessTable &base) : ValueWitnessTable(base) {}
};

struct ValueWitnessTableGenerator {
  static constexpr const ExtraInhabitantsValueWitnessTable table = { { 1 } };
};

int main() {}

error C2131: expression did not evaluate to a constant

note: failure was caused by evaluation of an assignment operation

note: while evaluating 'ExtraInhabitantsValueWitnessTable::ExtraInhabitantsValueWitnessTable(ExtraInhabitantsValueWitnessTable{ValueWitnessTable{(null)}}, ValueWitnessTable{size=1})'

What's going on here - do the standards allow this? Is this a C++ 17 feature?

Also, how would I work around this? I need the behaviour of member-wise initializing the base class (because there is stuff that I've omitted involving macros etc.).

Upvotes: 1

Views: 81

Answers (1)

H Bellamy
H Bellamy

Reputation: 22705

So I figured out the solution to this issue: use initializer lists instead:

struct ValueWitnessTable {
  int size;
};

struct ExtraInhabitantsValueWitnessTable : ValueWitnessTable {
  constexpr ExtraInhabitantsValueWitnessTable(const ValueWitnessTable &base) : ValueWitnessTable{base.size} {}
};

struct ValueWitnessTableGenerator {
  static constexpr const ExtraInhabitantsValueWitnessTable table = { { 1 } };
};

int main() {}

For some reason initializer lists are supported as constexpr, but copy constructors that do the same thing are not.

Upvotes: 0

Related Questions