std :: is_constructible은 개인 생성자에 대해 일치하지 않는 값을 반환합니다


13

std::is_constructible개인 생성자 를 처리 하는 규칙은 무엇입니까 ? 다음 코드가 주어진다 :

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

이것은 프린트 0( ideone )입니다. 즉, T기본적으로 구성 할 수 없습니다.

주석 처리 된 행의 주석을 해제하면 11( ideone ) 이 인쇄 되므로 갑자기T 기본 구성 가능하게되었습니다.

두 결과를 모두 뒷받침하는 추론을 찾을 수는 있지만 주석 처리 된 줄을 포함 시키면 두 번째 결과가 어떻게 바뀌는 지 이해할 수 없습니다. 이것이 어떻게 든 UB를 호출합니까? 이것은 컴파일러 버그입니까? 아니면 std::is_constructible실제로 일관성이 없습니까?


1
GCC 버그처럼 00
보이며

1
c ++ 17 g ++ 9.2.1 / g ++-10.0으로 내 컴퓨터에서 컴파일하고 std :: is_constructible <...> :: value를 is_constructible_v <...>로 바꿀 때 알 수있는 또 다른 이상한 생각은

1
@mutableVoid 실제로- ::value버전은 이전 버전의 출력도 변경할 수있는 것 같습니다 : godbolt.org/z/zCy5xU 주석 처리 된 주석 처리를 제거하고 gcc에서 모두 1 : s가됩니다.
Ted Lyngmo

1
그것을 고치는 또 다른 방법 : godbolt.org/z/EKaP3r 기본적으로 이것은 일종의 평가 순서 버그입니다.
Marek R

2
@mutableVoid 함수 템플릿을 인스턴스화 할 필요조차 없습니다. 이 예제에서는 반환 false되지만 함수 템플릿의 주석 처리가 없으면 갑자기 반환합니다 true. godbolt.org/z/zqxdk2
Ted Lyngmo

답변:


3

std::is_constructiblefalse생성자에 액세스 할 수 없으므로이 시나리오에서 리턴해야합니다 .

질문 아래에서 지적했듯이 질문에 설명 된 동작은 GCC / libstdc ++의 버그로 인해 발생합니다. 버그는 여기보고되었으며 Bugzilla에 따르면 꽤 오랫동안 해결되지 않은 템플릿 함수의 클래스에 대한 액세스 제어 버그로 인한 것이 아닌지와 관련이 있습니다. 두 버그 사이의 관계는 두 버그 사이의 연결을 먼저 감지 한 것으로 보이는 Jonathan Wakely의 Bugzilla 의견에서 가져 왔습니다.

이는 생성자를 비공개로 만드는 대신 생성자를 삭제할 때 GCC에서이 시나리오의 동작이 올바르게된다는 사실에 의해 암시됩니다.

class Class {
    Class() = delete;
};

어떤 인쇄 출력 000각각. 이것은 올바른 결과입니다 ( clang개인 생성자와 함께 시나리오에서 올바르게보고합니다).

이것은 줄을 주석 처리 할 때 관찰 된 동작의 변화를 설명 할 수 있습니다 . 템플릿 구조 의 함수 내에서 액세스 검사가 작동하지 않고 생성자가 액세스 할 수없는 경우 생성자가 액세스 할 수 있다고보고하기 때문입니다. 다음 줄에서 또는 완전히 다른 위치에서 특성을 다시 확인하면 ( 여기서 와 같이) 이미 인스턴스화되어 잘못된 답을 얻습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.