std :: is_constructible gibt einen inkonsistenten Wert für den privaten Konstruktor zurück

13

Nach welchen Regeln werden std::is_constructibleprivate Konstruktoren behandelt? Gegeben den folgenden Code:

#include <iostream>

class Class {
private:
    Class() { }
};

template <typename T>
class Test {
public:
    static void test() {
        std::cout
            //<< std::is_constructible<Class>::value
            << std::is_constructible<T>::value
            << std::endl;
    }
};

int main() {
    Test<Class>::test();
}

Dieser Druck 0( ideone ) ist also Tnicht standardmäßig konstruierbar.

Ohne die kommentierte Zeile zu kommentieren, wird sie gedruckt 11( ideone ), so dass sie plötzlichT standardmäßig konstruierbar wurde.

Ich konnte Gründe finden, um beide Ergebnisse zu unterstützen, aber ich verstehe nicht, wie das Einfügen der kommentierten Zeile das Ergebnis der zweiten ändert. Ruft das irgendwie UB auf? Ist das ein Compiler-Fehler? Oder ist das std::is_constructiblewirklich inkonsistent?

Zennehoy
quelle
1
Sieht aus wie ein GCC-Fehler, klirrte 9 Drucke00
Yksisarvinen
1
Ein anderer seltsamer Gedanke, den ich beim Kompilieren auf meinem Computer mit c ++ 17 g ++ 9.2.1 / g ++ - 10.0 und beim Ersetzen von std :: is_constructible <...> :: value durch is_constructible_v <...> bemerke, ist, dass der Ergebnis ändert sich zu 00
mutableVoid
1
@mutableVoid In der Tat - und es scheint, dass die ::valueVersion in der Lage ist, die Ausgabe derjenigen zu ändern, die davor stehen: godbolt.org/z/zCy5xU Kommentieren Sie die kommentierte Zeile aus und alles wird 1: s in gcc.
Ted Lyngmo
1
Eine andere Möglichkeit, das Problem zu beheben: godbolt.org/z/EKaP3r .
Marek R
2
@mutableVoid Sie müssen nicht einmal die Funktionsvorlage instanziieren, damit sie wahr wird. In diesem Beispiel wird zurückgegeben, falseaber wenn die Funktionsvorlage nicht kommentiert ist, wird plötzlich Folgendes zurückgegebentrue : godbolt.org/z/zqxdk2
Ted Lyngmo

Antworten:

3

std::is_constructiblesollte falsein diesem Szenario zurückkehren, da auf den Konstruktor nicht zugegriffen werden kann.

Wie unter der Frage ausgeführt, wird das in der Frage beschriebene Verhalten durch einen Fehler in GCC / libstdc ++ verursacht. Der Fehler wird hier gemeldet und bezieht sich laut Bugzilla auf einen Zugriffssteuerungsfehler für Klassen in Vorlagenfunktionen , der seit einiger Zeit nicht mehr behoben wurde. Die Beziehung zwischen den beiden Fehlern stammt aus Jonathan Wakelys Bugzilla-Kommentar, der anscheinend zuerst die Verbindung zwischen den beiden Fehlern erkannt hat.

Dies wird auch dadurch impliziert, dass das Verhalten dieses Szenarios in GCC beim Löschen des Konstruktors korrekt wird, anstatt ihn privat zu machen:

class Class {
    Class() = delete;
};

was druckt 0und 00jeweils. Dies ist die richtige Ausgabe (die clangim Szenario auch mit einem privaten Konstruktor korrekt meldet).

Dies könnte die beobachtete Verhaltensänderung beim Kommentieren in der Zeile erklären , da innerhalb der Funktion in der Vorlagenstruktur die Zugriffsprüfung nicht funktioniert und gemeldet wird, dass auf den Konstruktor zugegriffen werden kann, wenn dies nicht der Fall ist. Wenn das Merkmal in der nächsten Zeile oder möglicherweise an einer völlig anderen Stelle erneut überprüft wird (wie dies hier der Fall ist ), wurde es bereits instanziiert und liefert somit die falsche Antwort.

mutableVoid
quelle