`auto x = type {...}` синтаксис инициализации и `явный` оператор преобразования - clang vs gcc

Учитывая этот код (wandbox):

struct X
{
    explicit operator int() { return 0; }
};

int main()
{
    auto y = int{X{}};
}

И следующие параметры компилятора:

-std = С++ 1z -Wall -Wextra -Wpedantic


  • g++ (проверенные версии: 7, 6.1, 5.3) отказывается компилировать код со следующей ошибкой

    error: не может преобразовать 'X' в 'int' при инициализации

  • clang++ (проверенные версии: 4, 3.8, 3.6) счастливо компилирует сниппет.


Какой компилятор делает здесь правильную вещь?

cppreference кажется, что синтаксис auto var = type{...} должен вызывать явное преобразование.

Ответ 1

Использование http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4606.pdf Я думаю, что g++ ошибочен.

8.6.4 пункт 3.7:

- В противном случае, если в списке инициализаторов имеется один элемент типа E и либо T не является ссылочным типом, либо его ссылочным типом является ссылка, связанная с E, объект или ссылка инициализируются из этот элемент (путем инициализации копирования для инициализации списка копий или путем прямой инициализации для инициализации прямого списка); если сужение преобразования (см. ниже) требуется для преобразования элемента в T, программа плохо сформирована.

Значение того, что прямой init используется в этом случае типа некласса, что приводит нас к пункту 8.7.6.6:

- В противном случае, если тип источника является (возможно, cv-квалифицированным) классом тип, функции преобразования. Применимое преобразование функции перечислены (13.3.1.5), и выбран лучший через разрешение перегрузки (13.3). Пользовательское преобразование selected вызывается для преобразования выражения инициализатора в объект инициализируется. Если преобразование не может быть выполнено или неоднозначный, инициализация плохо сформирована.

И, наконец, в 13.3.1.5 говорится, что для прямой инициализации рассматриваются как явные, так и неявные преобразования:

- Рассматриваются функции преобразования S и его базовые классы. Те неявные функции преобразования, которые не скрыты внутри S и тип выхода T или тип, который может быть преобразован в тип T через стандартная последовательность преобразования (13.3.3.1.1) являются функциями кандидата. Для прямая инициализация, те явные функции преобразования, которые не скрыты внутри S и выдают тип T или тип, который может быть преобразован к типу T с квалификационным преобразованием (4.5) также являются кандидатом Функции. Функции преобразования, возвращающие тип cv-qual, считается, что для этой версии будет получена неквалифицированная версия этого типа процесс выбора кандидатских функций. Функции преобразования, которые return "reference to cv2 X" return lvalues ​​или xvalues, в зависимости от тип ссылки, типа "cv2 X" и поэтому считаются выход X для этого процесса выбора функций-кандидатов.