¿Por qué puedo usar auto en un tipo privado?
De alguna manera me sorprendió que el siguiente código se compilara y ejecutara (vc2012 y 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;
}
¿Es correcto que este código se compila bien? ¿Y por qué es correcto? ¿Por qué puedo usarlo auto
en un tipo privado y no puedo usar su nombre (como se esperaba)?
Las reglas para la deducción auto
son, en su mayor parte, las mismas que para la deducción tipo plantilla. El ejemplo publicado funciona por la misma razón: puede pasar objetos de tipos privados a funciones de plantilla:
template <typename T>
void fun(T t) {}
int main() {
Foo f;
fun(f.Baz()); // ok
}
¿Y por qué podemos pasar objetos de tipos privados a funciones de plantilla? Porque sólo el nombre del tipo es inaccesible. El tipo en sí todavía se puede utilizar, por lo que puede devolverlo al código del cliente.
El control de acceso se aplica a los nombres . Compare con este ejemplo del estándar:
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
}