std :: is_constructible zwraca niespójną wartość dla prywatnego konstruktora

13

Jakie są reguły, według których std::is_constructibleobsługuje się konstruktorów prywatnych? Biorąc pod uwagę następujący kod:

#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();
}

To drukuje 0( ideone ), tzn. TNie jest domyślnie możliwe do zbudowania.

Komentując komentarz, drukuje 11( ideone ), dzięki czemu Tnagle stała się domyślną konstrukcją.

Mogłem znaleźć uzasadnienie na poparcie obu wyników, ale nie rozumiem, w jaki sposób włączenie komentowanego wiersza zmienia wynik drugiego. Czy to w jakiś sposób wywołuje UB? Czy to błąd kompilatora? A może std::is_constructiblenaprawdę jest to niespójne?

zennehoy
źródło
1
Wygląda jak błąd GCC, 00
kliknął
1
Kolejną dziwną myślą, którą zauważam podczas kompilacji na moim komputerze z c ++ 17 g ++ 9.2.1 / g ++ - 10.0 i zastępowania wartości std :: is_constructible <...> :: is_constructible_v <...>, jest to, że zmiany wyniku na 00
mutableVoid
1
@mutableVoid Rzeczywiście - i wygląda na to, że ::valuewersja jest w stanie zmienić wyjście także tych, którzy się przed nim pojawili : godbolt.org/z/zCy5xU Odkomentuj komentarz i wszystko staje się 1: s w gcc.
Ted Lyngmo
1
Inny sposób, aby to naprawić: godbolt.org/z/EKaP3r, więc w zasadzie jest to jakiś błąd w kolejności oceny.
Marek R
2
@mutableVoid Nie trzeba nawet tworzyć szablonu funkcji, aby się spełnił. W tym przykładzie zwraca, falseale jeśli szablon funkcji nie jest komentowany, nagle zwraca true: godbolt.org/z/zqxdk2
Ted Lyngmo

Odpowiedzi:

3

std::is_constructiblepowinien powrócić falsew tym scenariuszu, ponieważ konstruktor jest niedostępny.

Jak wskazano poniżej, zachowanie opisane w pytaniu jest spowodowane błędem w GCC / libstdc ++. Błąd jest tutaj zgłaszany i, zgodnie z Bugzillą, związany z, jeśli nie spowodowany, błędem kontroli dostępu dla klas w funkcjach szablonów , który był nierozwiązany od dłuższego czasu. Związek między dwoma błędami pochodzi z komentarza Bugzilli Jonathana Wakely'ego, który wydaje się, że najpierw wykrył połączenie między tymi dwoma błędami.

Jest to również sugerowane przez fakt, że zachowanie tego scenariusza w GCC staje się poprawne po usunięciu konstruktora zamiast uczynienia go prywatnym:

class Class {
    Class() = delete;
};

który drukuje 0i 00odpowiednio. To jest poprawny wynik (któryclang poprawnie raportuje w scenariuszu z prywatnym konstruktorem).

To może tłumaczyć zaobserwowaną zmianę zachowania podczas komentowania w wierszu, ponieważ wewnątrz funkcji w strukturze szablonowej sprawdzanie dostępu nie działa i informuje, że konstruktor jest dostępny, gdy nie jest. Gdy cecha jest ponownie sprawdzana w następnym wierszu lub ewentualnie w zupełnie innym miejscu (tak jak ma to miejsce tutaj ), to już instancja, a tym samym daje złą odpowiedź.

mutableVoid
źródło