Обойти спецификаторы доступа с C ++ 0x decltype - PullRequest
3 голосов
/ 16 января 2011

Рассмотрим следующий код:

class A
{
private:
    class B {};
public:
    B f();
};

A a;

A::B g()
{
    return a.f();
}

Компилятор отклоняет это - g не может вернуть A :: B, потому что A :: B является приватным.

Но предположим, что теперь я использую decltype, чтобы указать возвращаемое значение g:

class A
{
private:
    class B {};
public:
    B f();
};

A a;

decltype(a.f()) g()
{
    return a.f();
}

Внезапно он прекрасно компилируется (с g ++> = 4.4).

Так что я в основном использовал decltype, чтобы обойти спецификатор доступа способом, которого я не смог бы в C ++ 98.

Это намеренно? Это хорошая практика?

1 Ответ

5 голосов
/ 16 января 2011

Доступ распространяется только на имена (и, как особый случай, на конструкторы / деструкторы). Это не относится к самим сущностям. Спецификация дополнительно уточняет

[Примечание: поскольку контроль доступа применяется к именам, если контроль доступа применяется к имени typedef, рассматривается только доступность самого имени typedef. Доступность объекта, на который ссылается typedef, не рассматривается. Например,

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
}

- конечная нота]

Так что то, что вы обнаружили здесь, не удивительно. Вы можете получить тип A::B даже в C ++ 03, когда берете адрес f, произнося &A::f и передавая его в шаблон функции, определяющий тип возврата.

...