Почему decltype не разрешен для частных переменных-членов?

Предположим, что у меня есть класс:

class Foo
{
  std::vector<int> bar;

public:
  std::vector<int>& get_bar() { return bar; }
};

и позже, я хочу другую переменную где-то еще, которая имеет тот же тип, что и bar. Для меня было бы разумно, если бы я мог это сделать:

decltype(Foo::bar) clone_of_bar;

Но это не работает. Компилятор сообщает мне: std::vector <int> Foo:: bar 'является закрытым.

Итак, мне нужно использовать что-то вроде этого:

std::remove_reference<decltype(std::declval<Foo>().get_bar())>::type clone_of_bar;

Что работает, но выглядит как полный беспорядок. Может быть, есть более простой способ сделать это; Я не совсем уверен. Но я действительно хочу знать, почему я не могу просто использовать decltype(Foo::bar). Почему кому-то нужно, чтобы bar был закрыт? Это не похоже на то, что я действительно обращаюсь к переменной.

decltype - новая функция языка. Я просто не понимаю, почему он был разработан, чтобы не работать с частными переменными.

Ответ 1

В терминах терминов языка bar - это имя, чтобы использовать его в выражении decltype, компилятор должен выполнять обычный поиск имени, что соответствует контролю доступа.
Почему decltype был разработан по-другому для остальной части языка? Вы не представили убедительных аргументов в пользу того, почему это не должно соответствовать, например, sizeof.

Как автор класса, я не хочу, чтобы вы могли запрашивать данные частной реализации, подобные этому. Если бы я хотел, чтобы тип был полезен вне класса, я бы определил публичный typedef, рассказывающий вам, какой он тип.

и позже, я хочу другую переменную где-то еще, которая имеет тот же тип, что и bar

Вам нужна "другая переменная" того же типа, что и частная реализация? Поэтому, если автор класса Foo реорганизует свой код и заменяет этот тип некоторыми другими деталями реализации, внезапно ваш код изменяет значение и не связанный код может внезапно прекратить компиляцию или молча иметь другое поведение, потому что этот код глупо полагался на личные данные, которые были ничто из его бизнеса. Это установит связь между частями частной реализации и несвязанным кодом, который может быть неизвестен даже автору Foo! Это ужасная идея.

Ответ 2

decltype(Foo::bar) работает внутри Foo.

Вне Foo вы даже не должны знать, что Foo имеет член с именем bar (что означает private), поэтому, конечно, он не должен работать.