2014-12-07 3 views
21

Ich habe eine Klasse Dimension, die ich (wie all meine Klassen) in einer Datei Dimension.h definiert:Kann die consExpr-Klasse in einer Kopfzeile deklariert und in einer separaten CPP-Datei definiert werden?

class Dimension 
{ 
public: 

    constexpr Dimension() noexcept; 

    constexpr Dimension(int w, int h) noexcept; 

    int width; 
    int height; 

}; 

Ich dachte, ich könnte, wie in allen meinen Klassen, die Definition in einem separaten Dimension.cpp setzen :

#include "Dimension.h" 

constexpr Dimension::Dimension() noexcept : width(0), height(0) {} 

constexpr Dimension::Dimension(int w, int h) noexcept : width(w), height(h) {} 

aber wenn ich versuche, um die Klasse zu verwenden, der Compiler sagt mir:

Warnung: Inline-Funktion 'constexpr Dimension::Dimension()' verwendet, aber nie definiert

und beim Verknüpfen:

undefinierte Bezugnahme auf 'pong::graphics::Dimension::Dimension()'

(gleich mit dem anderen Konstruktor)

Wenn ich definiere, die Klasse in dem Header wie folgt:

class Dimension 
{ 
public: 

    constexpr Dimension() noexcept : width(0), height(0) {} 

    constexpr Dimension(int w, int h) noexcept : width(w), height(h) {} 

    int width; 
    int height; 

}; 

und weglassen der .cpp-Datei, alles funktioniert gut.

Ich benutze GCC 4.9.2. Warum funktioniert die separate Definition nicht?

+7

Der ganze Sinn einer constexpr-Funktion besteht darin, die Funktion zur Kompilierzeit auswerten zu können.Das wäre ziemlich schwierig, wenn der Compiler den Körper der Funktion nicht sehen kann. –

+2

_ "Warum funktioniert die separate Definition nicht?" _ - Weil die Sprache dies nicht zulässt. Akzeptiere es, mach es richtig, geh weiter. –

+0

Ich habe das schon vermutet, aber ich bin mir nicht ganz sicher, ob ich (vielleicht mit Referenzen) erklären kann, warum es genau passiert. Ich habe beim googlen nichts darüber gefunden, daher dachte ich mir, dass eine neue Frage angemessen wäre. –

Antwort

27

Wenn in der Kopfzeile keine constexpr-Funktion definiert ist, kann der Compiler während der Kompilierung aller anderen Quelldateien die Definition der constexpr-Funktionen nicht sehen.

Offensichtlich, wenn es die Definition der Funktionen nicht sehen kann, kann es nicht die erforderlichen Schritte ausführen, um sie zur Kompilierzeit zu berechnen. Daher müssen alle constexpr Funktionen überall definiert werden, wo sie verwendet werden.

Dank @IgorTandetnik:
[dcl.constexpr] §7.1.5/2

constexpr Funktionen und constexpr Konstrukteure sind Inline implizit.

[basic.def.odr] §3.2/4

eine Inline-Funktion wird in jeder Übersetzungseinheit definiert werden, in dem es odr-verwendet wird.

5

Was Sie fragen kann erreicht werden, mit einer erheblichen Einschränkung: die constexpr Funktion kann dann nur aus dem Inneren der Übersetzungseinheit aufgerufen werden (das heißt Quelldatei), in dem sie definiert ist. Dies ist für das von Ihnen angegebene Beispiel nicht geeignet, da der Konstruktor zur öffentlichen Schnittstelle der Klasse gehört. Es kann jedoch in anderen Fällen, z.B. um private Methoden als consxpr zu definieren und dann ihre Rückgabewerte in Ausdrücken zu verwenden, die zur Kompilierungszeit bekannt sein müssen, z. Template-Instanziierungen, Switch-Anweisungsbezeichnungen usw.

Verwandte Themen