Bitte geben Sie die folgende Typdefinition berücksichtigen:nicht-ODR-Typ verwendet literal Erstellen
struct lit
{
enum { A, B } value;
constexpr lit() : value(A) { }
constexpr lit(int) : value(B) { }
};
Gemäß dem Standard 14 C++ (3,9/10) qualifiziert dieser Art als Literal-Typ. Als nächstes betrachten Sie bitte folgende Nutzungsszenario:
struct foo
{
static constexpr lit a { };
static constexpr lit b { 10 };
static constexpr int i { 42 };
};
int main()
{
lit a = foo::a;
lit b = foo::b;
int i = foo::i;
std::cout << "a=" << a.value << std::endl;
std::cout << "b=" << b.value << std::endl;
std::cout << "i=" << i << std::endl;
return 0;
}
Abschnitt 9.4.2/3 der Norm, die zwar nicht direkt die besagt, bedeutet, dass ich muss sie nicht angeben Definition für static constexpr
Mitglieder, es sei denn, sind odr-used (zB in Betracht ziehen foo::i
).
Wenn ich das oben mit clang kompiliere, beschwert es sich, dass ich Definitionen für foo::a
und foo::b
vermisse, da es denkt, dass sie odr-used sind. Siehe Beispiel unter coliru.
gcc dagegen schluckt es einfach gut und druckt glücklich das richtige Ergebnis aus. Auch hier ist ein Beispiel auf coliru.
Also, meine Frage ist zweifach:
Sind
foo::a
undfoo::b
wirklich odr-Einsatz? Und wenn ja, bitte erläutern Sie, warum und wie sie sich vonfoo::i
unterscheiden.Welche Änderungen
lit
getan werden müssen, um sie fürfoo::a
undfoo::b
out-of-Klassendefinitionen nicht benötigen? Mit anderen Worten, ich möchtefoo::a
undfoo::b
so verhalten wiefoo::i
.
UPDATE:
Es scheint, Barry Antwort in Bezug auf lit
richtig sein odr verwendet werden. Zur Veranschaulichung, wenn ich die folgende Funktion hinzu:
void bar(const int& x)
{
std::cout << "bar(" << x << ")" << std::endl;
}
und die folgende Zeile zum Haupt:
bar(foo::i);
gcc jetzt klagt auch.
Aber ich denke, das fällt unter eine Ausnahme in [basic.defodr]/3, weil 'lit' einen * trivialen * Kopierkonstruktor hat, der verwendet wird, um die lvalue-to-rvalue-Konvertierung durchzuführen. – Brian
@Barry, danke für deine Antwort, aber was ist mit 3.2/3 ... oh yeah, das ist, was Brian über –
sagt @Brian Es ist ein sehr ungeschickt formulierter Satz. Es besagt, dass es die Lvalue-to-rvalue-Konvertierung ist, die keine nicht-trivialen Funktionen aufruft? Aber egal, wo konvertieren wir in rvalue? – Barry