Это должно быть правильно сформировано, и поэтому это ошибка gcc.
Мы заканчиваем инициализацию агрегата через [stmt.return]p2 в котором говорится:
… Оператор return со списком инициализации в фигурных скобках инициализирует объект или ссылку, которые должны быть возвращены из функции путем инициализации списка копий ([dcl.init.list]) из указанного списка инициализаторов. …
затем [dcl.init.list]p3.2 говорит:
В противном случае, если T является агрегатом, выполняется агрегатная инициализация ([dcl.init.aggr]). …
В этот момент мы можем задаться вопросом, является ли это сужающим преобразованием и, следовательно, неправильно сформированным, но [dcl.init.list]p7 не имеет каких-либо пунктов, которые охватывают этот случай, и никакие другие случаи в [dcl.init.list] не применяются, чтобы сделать это неправильно сформированным.
Мы можем видеть на аналогичном примере, который удаляет enum из уравнения, но сохраняет битовое поле, показывает, что ни gcc, ни clang не дают нам сужающую диагностику преобразования, что, как мы ожидаем, будет иметь место, хотя эта аналогичная проблема покрывается [dcl.init.list]p7.4, хотя и не плохо- сформировано:
struct S2 {
int e : 2 ;
int dummy ;
} ;
S2 foo( int x ) {
return {x, 100} ;
}
посмотрите, как это работает в godbolt
Как видно, gcc не имеет проблем в других контекстах, т.е.
S f(E e1, int x) {
S s {e1,100} ;
return s;
}
Таким образом, у вас есть обходные пути.
person
Shafik Yaghmour
schedule
07.09.2018
10:9: warning: 'S::e' is too small to hold all values of 'enum class E'
для любого размера битового поля, кроме 32, а clang не предупреждает об этом, даже когда диапазон enum действительно не подходит. возможно, эта особая обработка битовых полей отчасти является причиной того, что GCC не может выполнить агрегатную инициализацию? - person Gem Taylor   schedule 06.09.2018