Валиден ли дефолтный инициализатор для шаблонной ссылки?
template <typename T>
class A {
A(int& x): ref{x} {}
T& ref{}; // <-
}
Валидный ли такой код? Мы можем инициализировать класс с помощью конструктора, но при этом default member initializer для ссылки всегда ill-formed.
Ответы (2 шт):
Если “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&
Как-то так, надеюсь достаточно понятно, если что, готов дополнить свой ответ. Всех благ
Код валиден, поскольку инициализатор члена по умолчанию не используется и поэтому игнорируется.
[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