Конструктор из rvalue ссылки на базу - жизнеспособный (gcc) или нет (лязг) - кто прав - PullRequest
0 голосов
/ 05 октября 2018

Недавно была проблема с комплиментами, иллюстрируемая этим фрагментом:

struct Base
{
};

template<typename T>
struct A : Base
{
    A(){}
    A(Base&&) {}
};

A<int> foo()
{
    A<double> v;
    return v;
}


int main()
{
    auto d = foo();
    return 0;
}

Gcc говорит, что все в порядке, но clang не согласен и говорит: «Конструктор-кандидат недопустим: нет известного преобразования из« A »в« Base && ».'для 1-го аргумента A (Base &&) {} ", убедитесь сами: https://godbolt.org/z/Y7mwnU

Сможет ли кто-нибудь из добрых читателей помочь с некоторыми стандартами поддержать любую точку зрения?

1 Ответ

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

лязг здесь правильный.Filed 87530 .

Правило для операторов возврата: [class.copy.elision] / 3 :

В следующем экземпляре-при инициализации, операция перемещения может использоваться вместо операции копирования:

  • Если выражение в операторе return ([stmt.return]) является (возможно, заключено в скобки) id-выражение , которое именует объект с автоматической продолжительностью хранения, объявленным в теле, или параметр-объявление-условие самой внутренней функции, или лямбда-выражение , или
  • , если операндом throw-выражения является имя энергонезависимого автоматического объекта (кроме функции или параметра catch-clause ), область действия которого не выходит за пределыконец самого внутреннего охватывающего блока try (если он есть), разрешение перегрузки

для выбора конструктора для копии сначала выполняется так, как если бы объект был обозначен значением r.Если первое разрешение перегрузки не удалось или не было выполнено, или если тип первого параметра выбранного конструктора не является rvalue-ссылкой на тип объекта (возможно, cv-qualified) , разрешение перегрузки выполняется снова, рассматривая объект как lvalue.[Примечание: это двухэтапное разрешение перегрузки должно выполняться независимо от того, будет ли выполнено копирование.Он определяет конструктор, который будет вызван, если elision не выполняется, и выбранный конструктор должен быть доступен, даже если вызов исключен.- конец примечания]

Акцент на шахте.

Мы встречаемся с первым маркером, возвращаем id-выражение , которое называет энергонезависимый автоматический объект,Таким образом, мы выполняем разрешение перегрузки, как если бы это было значение.Это разрешение перегрузки успешно, есть конструктор, который принимает Base&&.Однако обратите внимание на жирную часть.Тип этого параметра: , а не - ссылка на тип объекта.

Следовательно, мы снова попытаемся рассмотреть объект как lvalue.Это разрешение перегрузки не удается.

В результате программа некорректно сформирована.

...