Ich muss überprüfen, ob eine Klasse C
einen Standardkonstruktor hat, entweder implizit oder benutzerdefiniert, und entweder public
, protected
oder private
.
Ich habe versucht, std::is_default_constructible<C>::value
zu verwenden, was true zurückgibt, wenn C
einen public
Standardkonstruktor (entweder implizit oder benutzerdefiniert) hat, aber false
, wenn C
einen protected
oder private
Standardkonstruktor hat ( scheint jedoch das Standardverhalten zu sein.)
Gibt es eine Möglichkeit zu überprüfen, ob eine Klasse einen protected
oder private
Standardkonstruktor hat?
Hinweis (falls das helfen kann): Die Überprüfung wird von einer Funktion durchgeführt, die friend
der zu prüfenden Klasse C
ist.
Ich muss diese Prüfung durchführen, um Objekte zu erzeugen, die den nullptr
Zeigern des m_objs
Tupels entsprechen, Mitglied eines Foo
Objekts (partielle Foo Definition unten):
welches als:
verwendet werden soll %Vor% Beispiel oben behauptet, weil std::is_default_constructible<B>::value
falsch ist, obwohl B
einen [privaten] Standard-Ctor und Foo<A,B>
einen Freund von B hat.
Ich werde ein vereinfachtes Beispiel vorstellen, um die Dinge zu vereinfachen. Dann können Sie es an Ihre Foos-Klasse anpassen. Die Idee ist, meine Templates-Klasse wie folgt zu spezialisieren:
%Vor%Beachten Sie, dass der Kandidat std :: true_type immer gültig ist, solange X einen Standardkonstruktor hat, unabhängig davon, ob es privat, geschützt oder öffentlich ist. Testen Sie es jetzt
%Vor% Das Problem besteht darin, dass, wenn eine Klasse weder einen öffentlichen noch einen geschützten oder privaten Standardkonstruktor hat, die einfache Standarddefinition einer Instanz einen Kompilierungsfehler und keine Laufzeitausnahme ergibt. Der Test ist also einfach: Wenn dieser Ausdruck in einer Friend-Funktion C c;
kompiliert wird, hat die Klasse einen Standard-Ctor, entweder public, protected oder private.
Siehe Beispielcode:
%Vor%Aber ich konnte mir einen Laufzeittest nicht vorstellen ...
Mein Verständnis ist, dass Sie überprüfen möchten, ob Ihr friend
standardmäßig eine Klasse erstellen kann. Der Trick ist, dass Sie SFINAE innerhalb des Umfangs der Funktion friend
haben müssen. Um dies zu tun, benötigen Sie Vorlagen. Um lokale Vorlagen zu haben, benötigen Sie generische Lambdas.
Wir beginnen mit einem Overloader, in den wir mehrere Lambdas eingeben können. Vielleicht gibt es einen besseren Weg, dies zu schreiben:
%Vor%Dann übergeben Sie überladene, generische, SFINAE-d Lambdas (C ++ 14 erforderlich). Sagen wir, wir haben:
%Vor%Dann könnten wir schreiben:
%Vor% Wenn works
ein Freund ist, ist die erste Überladung praktikabel und bevorzugt - also bekommst du das, was ein Q
erzeugt, weil es möglich ist. Wenn works
kein Freund ist, ist die erste Überladung nicht praktikabel und Sie erhalten die zweite Überladung.
Der Schlüssel ist, dass wir die Konstruktion von Q
(der typename decltype(x)::type()
Teil) innerhalb von works()
testen - also wird es entweder von Freundschaft gedeckt sein.
Für Ihre spezielle Verwendung wäre das also:
%Vor%