중괄호가있는 참조 유형의 변수에 대한 decltype

Dec 15 2020

다음 코드를 고려하십시오 .

#include <type_traits>

int main() {
    const int& p = 42;
    auto v1 = decltype(p){};
    static_assert(std::is_same_v<decltype(v1), int>);
    
    decltype(p) v2{};
    static_assert(std::is_same_v<decltype(v2), const int&>);
    // auto v3 = X(const int&)X {};
}

유형은 v1로 추론됩니다 int. 같은 시간 유형에서 v2예상대로로 추론된다 const int&. 에 대한 첫 번째 단계는 v1유형 별칭을 하나 더 추가 한 using T = decltype(p);다음 auto v4 = T{};. 이 표현식 ( decltype(p){}또는 T{})은 컴파일러에서 어떻게 처리됩니까? 그 {}부분이 인스턴스화를위한 것이라는 것을 알고 있지만 결과 유형이 v1참조 유형이 아닌 이유는 무엇입니까?

또 다른 질문 : (대신 ) 명시 적으로 언급 된 유형 v3v1사용 하는 것과 동일한 유형의 변수 를 선언하는 방법이 있습니까?const int&decltype(p)

표준에 대한 모든 링크를 주시면 감사하겠습니다.

답변

1 Enlico Dec 15 2020 at 00:48

(비정 투표자에게 : Scott Meyers를 인용하는 것이 표준을 인용하는 것과 같지 않다고 생각하여 반대표를 던졌다면, 오 글쎄요 ...)

Effective Modern C ++ 에서 읽을 수있는 것처럼 ( 해당 링크에서 검색하여 도달 할 수 있는 정오표 의 일부가 추가되어 Case 2:다음 읽기가 더 간단 해지지 만 질문에 필수적인 것은 아닙니다) :

경우 ParamType비 참조 경우 [...] expr의 타입이 레퍼런스 인, 기준 부분을 무시한다. [...] exprconst이면 그도 마찬가지입니다. 인 경우 volatile무시하십시오.

param선언 지정자는 어디 입니까? 귀하의 경우에는 단지 auto, 즉 비 참조입니다.

즉, v1일반 auto(아님 auto&), 즉 복사 를 통해 생성 하므로 참조인지 아닌 엔티티로 초기화하는지 여부 const( volatile또는 포함하지 않음, fwiw) 로 초기화하는지 여부는 중요하지 않습니다 . 당신이 그것을 복사하고 있기 때문입니다.

더 간단한 경우를 생각해보세요.

int i = 3;
int& p = i;
auto v1 = p;

멀리로 v1우려, 정말이 하나 initalized 여부를 중요 (아니다 i) 또는 다른 ( p하는) 이름이 같은 그 개체가 가지고있는 어떤 값의 사본을 얻을 수 있기 때문에, 실체가 알려져있다.

auto유형 추론은 템플릿 유형 추론과 동일하게 작동하며 (이 경우에는 관련이없는 중괄호 이니셜 라이저를 처리하는 방식의 차이를 제외하고) 둘 다 Scott Meyers의 Effective Modern C ++를 참조 할 수 있습니다 .