2016-09-06 8 views
1

this answer을 읽은 후, 나는 몇 가지 테스트를했고 나는 다음과 같은 코드를 내놓았다 : 내가 생각, main()친구 연산자 <<와 템플릿 클래스 멤버의 개인 액세스

#include <iostream> 

template <typename T> 
class Test { 
    int val{42}; 

    friend std::ostream & operator << (std::ostream & flux, Test const & instance) { 
     return flux << Test<char>{}.val; 
    } 
}; 

int main() { 
    std::cout << Test<int>{}; 
    return 0; 
} 

Test<int>를 사용하여 해당 operator<<는 할 수 없었다 액세스 Test<char>{}.val. 그러나 놀랍게도, GCC는 정상적으로 편집되었습니다.

그런 다음 Clang과 Visual Studio에서 테스트 한 결과, 둘 다 예상과 같이 개인 회원 오류가 발생했습니다 (GCC/Clang demo 참조).

올바른 컴파일러는 무엇입니까?

도 궁금합니다. extrovert 버전이 링크에 언급되어 있습니다. 또는 operator<<의 에 대한 개인 액세스는 Test<T> (T! = U 일 때)입니까? 실용적인 예가 있습니까?

+0

어떤 버전의 C++에 대해 묻고 있습니까? 그 컴파일러의 어떤 버전을 사용 했습니까? –

+0

표준 (C++ 11)에서이 프로그램이 유효하다고 여겨지는 증거는 없지만 GCC가 그러한 명백한 오류로 보이는 것을 받아들이는 것은 의심 스럽습니다. –

+1

아마도 누군가가 14.5.4/5 ... 11.3/2를 잘못 읽은 것 같아요. 내가 찾은 것이 무엇이든 모순되는 것은 아닙니다. 나는 당신이 GCC의 Bugzilla에이 글을 올리라고 제안하고, devs가 어떤 결론을 내렸는지를 알려주는 답변을 되돌려 준다. –

답변

0

믿을만한 인스턴스를 매개 변수에서 사용하는 대신 사용자가 새 인스턴스를 만들면 (예 : 외부 인스턴스에서와 같이) 액세스가 다시 설정되기 때문에 Clang/VS가 올바른 동작을 사용한다고 생각합니다. .

여분의 질문에 관해서는 외향적 인 실용적인 예를 생각할 수는 없지만 C++의 많은 것들과 같은 이유로 거기에 있다고 상상해보십시오. 원하는 경우 그렇게 할 수 있습니다. 한 유형에서 다른 유형으로 변환하는 데 사용할 수 있습니까? 확실하지, 미안해 ^^;

추신 : 원래 혼란에 사과드립니다.

+1

_ "귀하가 링크 한 데모는 기본적으로 Clang 또는 VS와 동일한 오류를 보여줍니다." –

+0

"g ++ -std = C++ 11 main.cpp && echo"GCC OK "&& clang ++ -std = C++ 11 main.cpp main.cpp : 8 : 37 : 오류 : 'val'은 '테스트 '개인 부재 반환 플럭스 << Test {} .val; ^ MAIN.CPP : 13 : 15 : 주 : 여기에서 요청 된 멤버 함수의 인스턴스화 '연산자 <<' 표준 : COUT << Test {}; . ^ MAIN.CPP : 5 : 9 : 참고 :; ^ 1 오류가 발생 "그것은 거의 정확하게 내가 폼 연타를 가지고 무엇을 암시 적으로 여기에 개인 INT의 발 {42} 선언했다. –

+1

그 결과가 출력됩니다. GCC는 진단을 내리지 않습니다. 그래서'echo "GCC OK"가 있습니다 - 첫번째 진단이 clang 호출에서 나온 것을 보여주는 것입니다. –