Какое правило разрешения перегрузки применяется здесь? - PullRequest
0 голосов
/ 24 января 2019

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

Моя цель состояла в том, чтобы создать новый временный экземпляр с помощью конструктора копирования, а затем передать этот объект методу, чтобы передать ссылку на r-значение.

И есть перегруженные методы, которые принимают l-значение, r-значение, поэтому я ожидал, что будет вызван перегруженный метод r-значения, но это не так.

class Kdy {
 public:
  Kdy() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

  Kdy(Kdy&&) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

  Kdy(const Kdy&) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

  void DoAction(const Kdy&) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }

  void DoAction(Kdy&&) {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
  }
};  // Kdy

int main() {
  Kdy kdy1;
  Kdy kdy2;


  // DoAction(const Kdy&), Why??
  // kdy1.DoAction(Kdy(kdy2))
  kdy1.DoAction({kdy2});



  // Then why this works?
  // After copy-ctor, DoAction(Kdy&&) was invoked.
  kdy1.DoAction({ {kdy2} });



  // Then why this dosen't compile?
  // Since { {kdy2} } becomes Kdy&& 
  // { { {kdy2} } } should be Kdy(Kdy&&)
  // kdy1.DoAction({ { {kdy2} } });

  return 0;
}

Я прочитал перегрузкуссылочный документ несколько раз, но он мне наполовину ясен https://en.cppreference.com/w/cpp/language/overload_resolution

Кажется, что после сбора набора методов-кандидатов компилятор принимает решение, какой метод лучше всего подходит по приоритету сопоставления.

Итакочевидно, если есть несколько методов, принимающих std::initializer_list<Kdy> в качестве параметра, то эти методы выбираются(Я проверил это)

В таком случае, если точное совпадение подписи не удалось, какое правило перегрузки разрешения было применено в этом контексте?Что заставило компиляцию думать, что {kdy2} лучше подходит для const Kdy&, чем для Kdy&&?

Кроме того, почему { { { kdy2 } } } нельзя интерпретировать как Kdy(Kdy&&)?

Пожалуйста, скажитесвет на этого бедного парня.Спасибо!

1 Ответ

0 голосов
/ 24 января 2019

Давайте возьмем следующую часть стандарта в качестве ссылки:

[dcl.init.list]

  • (3.7) В противном случае, если T является типом класса, рассматриваются конструкторы. Применимые конструкторы перечисляются, и лучший выбирается через разрешение перегрузки.
  • (3.9) В противном случае, если список инициализатора имеет единственный элемент типа E и либо T не является ссылочным типом, либо его ссылочный тип связан со ссылкой на E, объект или ссылка инициализируются из этого элемента ...

Раздел (3.9) объясняет, почему DoAction({kdy2}) выбирает перегрузку DoAction(const Kdy&). Единственный элемент списка инициализатора - это lvalue типа Kdy, и из двух перегрузок DoAction только один может связываться с lvalue; выбранный.

В DoAction({ {kdy2} }) в инициализаторе нет ни одного элемента типа Kdy, (3.9) не используется и вводится значение для {{kdy2}}. В силу (3.7) рассматриваются конструкторы Kdy. Кандидатами являются Kdy(Kdy&&) и Kdy(Kdy const&).

Чтобы выбрать лучший, {kdy} пытаются преобразовать в параметры ctors, и снова применяя (3.9), выбранный конструктор является копирующим ctor. Затем значение prvalue привязывается к параметру DoAction, и из этих перегрузок DoAction(Kdy&&) является лучшим соответствием.

Для DoAction({ { {kdy2} } }) предпринимаются попытки, как и во втором случае, но при попытке преобразовать {{kdy2}} в параметры конструкторов это не удается, поскольку в списке инициализатора нет ни одного элемента типа Kdy и (3.7 ) не применяются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...