Почему я могу использовать auto в закрытом типе?
Я как-то удивился, что следующий код компилируется и запускается (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
для частного типа, тогда как я не могу использовать его имя (как ожидалось)?
Ответы
Ответ 1
Правила для auto
, по большей части, такие же, как для вывода типа шаблона. Приведенный пример работает по той же причине, что и объекты частных типов для шаблонов:
template <typename T>
void fun(T t) {}
int main() {
Foo f;
fun(f.Baz()); // ok
}
И почему мы можем передавать объекты частных типов в функции шаблона, спросите вы? Потому что только имя типа недоступно. Сам тип все еще можно использовать, поэтому вы можете вообще вернуть его к клиентскому коду.
Ответ 2
Контроль доступа применяется к именам. Сравните этот пример со стандартом:
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
}
Ответ 3
Этот вопрос уже очень хорошо ответил как холодом, так и Р. Мартиньо Фернандесом.
Я просто не мог упустить эту возможность ответить на вопрос с аналогией Гарри Поттера:
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;
}
Ответ 4
Чтобы добавить к другим (хорошим) ответам, вот пример из С++ 98, который показывает, что проблема действительно не связана с 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
}
Использование частного типа не запрещено, это только имя типа. Создание неназванного временного типа такого типа в порядке, например, во всех версиях С++.