Тернар позволил вызвать явный экземпляр конструктора неявно? - PullRequest
0 голосов
/ 09 октября 2018

Рассмотрим приведенный ниже код:

#include <cstdio>
struct A
{
    A(){}
    explicit A(const A&) {std::puts("copy");}
};

int main() 
{
    A a;
    true ? a : A();
    return 0;
}

Как я понимаю, троичный попытается скопировать a и потерпит неудачу, так как конструктор копирования явный, однако gcc компилирует это очень хорошо исоздает копию.Clang выдает ошибку, как и ожидалось.

Это ошибка в gcc?

Я использую gcc 8.1 и clang 7.0 в режиме c ++ 17, но я также пробовал все версии gcc в проводнике компилятора в режиме c ++ 98, и все они ведут себя одинаково.

1 Ответ

0 голосов
/ 09 октября 2018

Clang прав, отвергнув его, и это действительно ошибка GCC.Я процитирую n4659 (ближайший документ, который мне нужен к стандарту C ++ 17) для простоты.

Прежде всего, тип условного выражения в вашем примере, как указано [expr.cond] ¶6 должен быть prvalue типа A.

Теперь, согласно [expr.cond] ¶7 , выделение мое:

Стандартные преобразования Lvalue-to-rvalue , массива-в-указатель и функции-в-указатель выполняются для второго и третьего операндов.

a должен быть в состоянии пройти преобразование lvalue в rvalue.Который для a указан в [conv.lval] .23.2 (опять же, выделено мое) как

В противном случае, если T имеет тип класса, преобразование copy-initializes результирующий объект из glvalue.

Копирование инициализации A из A, в любом контексте, должно выбирать конструктор преобразования в разрешении перегрузки ( [over.match.copy] ¶1.1 ):

Конвертирующие конструкторы T являются функциями-кандидатами.

И явный конструктор копирования не являетсяконструктор преобразования ( [class.conv.ctor] ¶3 )

A неявный конструктор копирования / перемещения ([class.copy])является конвертирующим конструктором.

Соответствующая реализация C ++ не может принять условное выражение, которое вы написали, как правильно сформированное.

...