C ++ 11 Совокупная инициализация приватного члена, это правильно? - PullRequest
1 голос
/ 14 мая 2019

Правильно ли инициализировать закрытый член через агрегатную инициализацию при передаче его в качестве параметра в функцию класса владельца?Просто посмотрите на код ниже.

class A {
  struct S {
    int t, u;
  };
public:
  void f(const S& s) {}  
};

int main() {
  A a;
  a.f({1, 2}); // correct?
  return 0;
}

Я проверил стандарт и сети, и кажется, что нет точного ответа.Похоже, что механика выглядит следующим образом: * инициализированный скобками является общедоступной вещью, и поэтому пользователь не нарушает ограничения доступа.* неявное преобразование из инициализатора в «S» является внутренним для «S» и, следовательно, также подходит для компилятора.

Вопрос в том, есть ли какая-либо ссылка в стандарте, черновик или, по крайней мере, cppreference с описанием этогоповедение?

Ответы [ 2 ]

2 голосов
/ 14 мая 2019

Да, это правильно.Единственное, что личное о S - это имя.Контроль доступа только контролирует доступ через имя ( [class.access] p4 ).Таким образом, вы можете использовать черту типа, чтобы получить тип S, например, через тип f ( пример ).

Таким образом, это разрешено, потому что нет ограничений [dcl.init.agg] , который запрещает инициализацию «частных» типов.

Также есть заметка , найденная @ StephaDyatkovskiy.

0 голосов
/ 14 мая 2019

Неважно, официально ли он действителен;вам следует избегать этого углового случая.

Я бы сказал, что «действительно ли это C ++» - это неправильный вопрос здесь.

Когда вы смотрите на кусок кода и, попробуйте, как можете,вы не можете решить, должен ли он быть действительным C ++ или нет;и вы знаете, что это будет какой-то угловой случай, в зависимости от точной формулировки стандарта - обычно хорошая идея не полагаться на этот угловой случай, так или иначе.Зачем?Потому что другие люди тоже запутаются;они будут тратить время, пытаясь понять, что вы имели в виду;они будут искать его в стандарте - или, что еще хуже, не искать его и делать неверные предположения;и они будут отвлекаться от того, на чем им действительно нужно сосредоточиться.

Итак, с этим кодом я бы спросил себя: «Является ли тип S действительно закрытым? Неужели внешний код действительно не должен знать об этом?? "

Если ответ" Да, это так "- тогда я бы изменил f, чтобы взять параметры для конструктора S (и переслать их в ctor):

void f(int t, int u) { S {t, u}; /* etc. etc. */ }

Если ответ «Нет, код, вызывающий f(), может знать, что он передает ссылку S» - тогда я сделаю S общедоступным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...