개인 유형에서 자동을 사용할 수있는 이유는 무엇입니까? { int i; }; public:

다음 코드가 컴파일되어 실행된다는 것에 어떻게 든 놀랐습니다 (vc2012 & gcc4.7.2)

class Foo {
    struct Bar { int i; };
public:
    Bar Baz() { return Bar(); }
};

int main() {
    Foo f;
    // Foo::Bar b = f.Baz();  // error
    auto b = f.Baz();         // ok
    std::cout << b.i;
}

이 코드가 제대로 컴파일되는 것이 맞습니까? 왜 정확합니까? auto개인 유형으로 사용할 수 있는데 예상대로 이름을 사용할 수없는 이유는 무엇 입니까?



답변

auto대부분 의 경우 규칙 은 템플릿 유형 공제와 동일합니다. 게시 된 예제는 개인 유형의 객체를 템플릿 함수에 전달할 수있는 것과 같은 이유로 작동합니다.

template <typename T>
void fun(T t) {}

int main() {
    Foo f;
    fun(f.Baz());         // ok
}

그리고 왜 개인 유형의 객체를 템플릿 함수에 전달할 수 있습니까? 유형의 이름 만 액세스 할 수 없기 때문입니다. 유형 자체는 여전히 사용할 수 있으므로 클라이언트 코드로 반환 할 수 있습니다.


답변

액세스 제어는 이름에 적용됩니다 . 표준의이 예와 비교하십시오.

class A {
  class B { };
public:
  typedef B BB;
};

void f() {
  A::BB x; // OK, typedef name A::BB is public
  A::B y; // access error, A::B is private
}

답변

이 질문은 이미 chill과 R. Martinho Fernandes에 의해 매우 잘 대답되었습니다.

해리포터 비유로 질문에 대답 할 수있는 기회를 막을 수 없었습니다.

class Wizard
{
private:
    class LordVoldemort
    {
        void avada_kedavra()
        {
            // scary stuff
        }
    };
public:
    using HeWhoMustNotBeNamed = LordVoldemort;

    friend class Harry;
};

class Harry : Wizard
{
public:
    Wizard::LordVoldemort;
};

int main()
{
    Wizard::HeWhoMustNotBeNamed tom; // OK
    // Wizard::LordVoldemort not_allowed; // Not OK
    Harry::LordVoldemort im_not_scared; // OK
    return 0;
}

https://ideone.com/I5q7gw

해리 허점을 상기시켜 준 Quentin에게 감사드립니다.


답변

여기에 문제가 정말 함께 할 수없는 것을 보여 98 ++ C에서 예입니다, 다른 (좋은) 답변을 추가하려면 auto모두에서

class Foo {
  struct Bar { int i; };
public:
  Bar Baz() { return Bar(); }
  void Qaz(Bar) {}
};

int main() {
  Foo f;
  f.Qaz(f.Baz()); // Ok
  // Foo::Bar x = f.Baz();
  // f.Qaz(x);
  // Error: error: ‘struct Foo::Bar’ is private
}

개인 유형을 사용하는 것은 금지되지 않으며 유형의 이름 만 지정했습니다. 예를 들어, 모든 버전의 C ++에서 이름이없는 임시 유형을 작성해도됩니다.