Валиден ли дефолтный инициализатор для шаблонной ссылки?

template <typename T>
class A {
  A(int& x): ref{x} {}
  T& ref{}; // <-
}

Валидный ли такой код? Мы можем инициализировать класс с помощью конструктора, но при этом default member initializer для ссылки всегда ill-formed.


Ответы (2 шт):

Автор решения: Simon

Если “T” является ссылочным типом(допустим &int), то невалидна. ссылка должна быть сразу(при создании) привязана к объекту. А «{}» не дает объекта для привязки. Если “T” не ссылочный тип, то все валидно и значение по умолчанию (0, тк это int). Также в твоём конструкторе используется member initializer list => конструктор DMI (ref{}) игнорируется, но при всем при этом DMI все также должен быть семантически и синтаксически валидным для T. Исходя из вышесказанного я бы рекомендовал удалить default member initializer(DMI) и без него все будет инициализироваться:

template class A { public: A(int& x) : ref{x} {} // Корректная инициализация в списке T ref; // Без DMI };

Это также поможет при инстанциировании шаблона T = int&

Как-то так, надеюсь достаточно понятно, если что, готов дополнить свой ответ. Всех благ

→ Ссылка
Автор решения: Serge3leo

Код валиден, поскольку инициализатор члена по умолчанию не используется и поэтому игнорируется.

[class.base.init] 10

If a given non-static data member has both a default member initializer and a mem-initializer, the initialization specified by the mem-initializer is performed, and the non-static data member's default member initializer is ignored

[class.base.init] 11

A temporary expression bound to a reference member from a default member initializer is ill-formed

Там же [class.base.init] (C++26 11.9.3 п. 11, С++20 11.10.2 п. 11) есть очень похожий на вопрос поясняющий пример для случая, когда невалидный инициализатор члена ссылочного типа по умолчанию может использоваться, а может не использоваться:

// [Example 8:
struct A {
  A() = default;       // OK
  A(int v) : v(v) { }  // OK
  const int& v = 42;   // OK
};
A a1;                  // error: ill-formed binding of temporary to reference
A a2(1);               // OK, unfortunately
// —end example]

Если стандарта по рукой нет, то актуальный черновик: https://eel.is/c++draft/class.base.init

→ Ссылка