2016-10-13 9 views
12

Учитывая этот код (на wandbox):`авто х = тип {...}` синтаксис инициализации и `explicit` оператор преобразования - лязг против НКИ

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

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

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

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


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

    error: cannot convert 'X' to 'int' in initialization

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


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

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

+0

FWIW, MSVC счастливо компилируется тоже. –

+0

@Danh g ++ принимает 'int y {X {}}', который не должен приниматься, если рассматривается только неявное преобразование (так что либо это неправильно, либо другое неверно). – Holt

ответ

4

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

8.6.4 пункта 3.7 гласит:

— Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization); if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed.

Это означает, что прямая инициализация используется в данном случае типа неклассового, что приводит нас к 8.6 п 17.7:

— Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion functions are enumerated (13.3.1.5), and the best one is chosen through overload resolution (13.3). The user-defined conversion so selected is called to convert the initializer expression into the object being initialized. If the conversion cannot be done or is ambiguous, the initialization is ill-formed.

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

— The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not hidden within S and yield type T or a type that can be converted to type T via a standard conversion sequence (13.3.3.1.1) are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within S and yield type T or a type that can be converted to type T with a qualification conversion (4.5) are also candidate functions. Conversion functions that return a cv-qualified type are considered to yield the cv-unqualified version of that type for this process of selecting candidate functions. Conversion functions that return “reference to cv2 X” return lvalues or xvalues, depending on the type of reference, of type “cv2 X” and are therefore considered to yield X for this process of selecting candidate functions.

+0

После тщательного чтения стандартных кавычек, которые вы отправили, на самом деле это похоже на то, что 'g ++' в этом случае не так. Я зарегистрировал [ошибка # 77976] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77976) и связался с этим вопросом и вашим ответом. Благодаря! –

+0

Я думаю, что я нашел более старую ссылку на эту ошибку - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63999 –