vendredi 30 décembre 2016

Class-typed static constexpr field giving link-time errors in g++

I have this snippet of code I was testing today:

#include <iostream>

struct Literal {
    constexpr operator int() const { return 0; }
};

struct Class {
    constexpr static const Literal field0 = Literal();
};

int main(void) {
    std::cout << "Class::field0: " << Class::field0 << std::endl;
    return 0;
}

It compiles without errors (G++ 6.2.1), but unfortunately I get a link error when generating the executable:

/tmp/ccao6eTy.o: In function `main':
test-constexpr-static-field.cpp:(.text+0xa): undefined reference to `Class::field0'
collect2: error: ld returned 1 exit status
[Finished in 0.3s with exit code 1]

Reading this page I see this explanation:

If a static data member of LiteralType is declared constexpr, it must be initialized with an initializer in which every expression is a constant expression, right inside the class definition (...).

Then I went for the definition of what is a LiteralType, and I saw that:

A literal type is any of the following:

  • possibly cv-qualified class type that has all of the following properties:
    • has a trivial destructor,
    • is either
    • an aggregate type,
    • a type with at least one constexpr (possibly template) constructor that is not a copy or move constructor,
    • a closure type (since C++17)
  • all non-static data members and base classes are of non-volatile literal types.

Is it the case that Literal does not conform to a LiteralType? As I see it, it has a trivial constructor, and even has no internal state to avoid any troublesome issue with aggregate types or non-static fields on a literal type.

But considering it does conform (primarily because the program compiled without errors), why the link-time error? Is that a G++ bug, perhaps?

Aucun commentaire:

Enregistrer un commentaire