Pourquoi puis-je utiliser auto sur un type privé?

J’ai été en quelque sorte surpris que le code suivant comstack et s’exécute (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 << bi; } 

Est-il correct que ce code comstack bien? Et pourquoi est-ce correct? Pourquoi utiliser auto sur un type privé alors que je ne peux pas utiliser son nom (comme prévu)?

Les règles pour auto sont, pour la plupart, les mêmes que pour la déduction de type de modèle. L’exemple publié fonctionne pour la même raison que vous pouvez transmettre des objects de types privés aux fonctions de modèle:

 template  void fun(T t) {} int main() { Foo f; fun(f.Baz()); // ok } 

Et pourquoi pouvons-nous passer des objects de types privés aux fonctions de modèle, vous demandez-vous? Parce que seul le nom du type est inaccessible. Le type lui-même est toujours utilisable, ce qui explique pourquoi vous pouvez le renvoyer au code client.

Le contrôle d’access est appliqué aux noms . Comparez à cet exemple de la norme:

 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 } 

Cette question a déjà été très bien résolue à la fois par Chill et R. Martinho Fernandes.

Je ne pouvais tout simplement pas laisser passer cette occasion de répondre à une question avec une analogie de Harry Potter:

 class Wizard { private: class LordVoldemort { void avada_kedavra() { // scary stuff } }; public: using HeWhoMustNotBeNamed = LordVoldemort; }; int main() { Wizard::HeWhoMustNotBeNamed tom; // OK Wizard::LordVoldemort not_allowed; // Not OK return 0; } 

Pour append aux autres (bonnes) réponses, voici un exemple de C ++ 98 qui montre que le problème n’a vraiment rien à voir avec l’ auto du tout

 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 } 

L’utilisation du type privé n’est pas interdite, il ne s’agissait que de nommer le type. Créer un temporaire sans nom de ce type est correct, par exemple, dans toutes les versions de C ++.