2016-04-05 15 views
4

Bitte beachten Sie die folgenden Klasseeine delegierende Methode als constexpr Deklarieren, wenn die aufgerufene Funktion mit constexpr

template<class T> 
class foo 
{ 
public: 
    auto bar() { return m_t.bar(); } 

private: 
    T m_t; 
}; 

angegeben Wenn wir foo<T>::bar wollen nicht Werfen sein, wenn T::bar nicht-Wurf ist, können wir seine Erklärung ändern zu

auto bar() noexcept(noexcept(m_t.bar())) { return m_t.bar(); } 

Aber was können wir tun, wenn wir mit constexprfoo<T>::bar angegeben werden soll, sobald T::bar mit constexpr angegeben ist?

Können wir schreiben gerade

constexpr auto bar() noexcept(noexcept(m_t.bar())) { return m_t.bar(); } 

und es wird in jedem Fall arbeiten? Ich habe das mit clang 3.7 (C++ 17) getestet und es scheint der Fall zu sein, aber ich bin mir nicht sicher, ob der Compiler hier richtig funktioniert oder nicht.

+0

Denken Sie daran, dass 'constexpr' immer noch nur ein Hinweis ist, es kann zur Kompilierzeit ausgewertet werden, muss es aber nicht sein. Dies ermöglicht, dass Ihre Methodensignatur in beiden Fällen funktioniert, also ja, das ist gültig. –

Antwort

5

Von [dcl.constexpr]:

Wenn die instanzierte Vorlage Spezialisierung einer constexpr Funktionsvorlage oder Elementfunktion einer Klasse Vorlage würde nicht die Anforderungen für einen constexpr Funktion oder constexpr Konstruktor gerecht zu werden, ist, dass die Spezialisierung noch ein constexpr Funktion oder constexpr Konstruktor, obwohl ein Aufruf einer solchen Funktion nicht in einem konstanten Ausdruck angezeigt werden kann. Wenn keine Spezialisierung der Vorlage die Anforderungen für eine constexpr-Funktion oder einen constexpr-Konstruktor erfüllen würde, wenn sie als Nicht-Template-Funktion oder als Konstruktor betrachtet wird, ist die Vorlage fehlerhaft; keine Diagnose erforderlich.

Da gibt es T s, die ein constexpr X bar() haben könnten, die in einem konstanten Ausdruck verwendet werden können, ist die Vorlage in Ordnung. Wenn T einen nicht constexprbar() hat, wird foo::bar immer noch als constexpr betrachtet, kann aber nicht in einem konstanten Ausdruck erscheinen.

+0

Sie könnten diese Antwort erweitern, indem Sie darauf hinweisen, dass der Standardkonstruktor (und vielleicht andere spezielle Mitglieder, die nicht geprüft wurden) implizit "constexpr" sein kann (wenn alle Mitglieder constexpr sind), und dann kann das Schlüsselwort weggelassen werden. Auch wenn in 'bar() 'ein verbotenes Konstrukt existiert (ein' goto' oder 'new' usw.), wird der Compiler folgern, dass kein' T' 'bar' als' constexpr' darstellen kann. – TemplateRex

+0

@TemplateRex Das könnte gerade außerhalb des Geltungsbereichs sein? Ich möchte nicht, dass die Antwort nur alle Regeln von "constexpr" auflistet. (Und ja, das gleiche gilt auch für das Kopieren/Bewegen der Konstruktion/Zuweisung.) – Barry

+0

Ja, wahrscheinlich außerhalb des Geltungsbereichs. Obwohl ich mir etwas wie "constexpr (auto)" wünsche :) – TemplateRex

Verwandte Themen