Понимание вывода аргумента шаблона с помощью rvalue/lvalue

это продолжение от шаблон функции не распознает lvalue

позволяет играть со следующим кодом:

#include <iostream>
template <class T>
void func(T&&) {
  std::cout<<"in rvaluen";
}

template <class T>
void func(const T&) {
  std::cout<<"in lvaluen";
}

int main()
{
    double n=3;
    func<double>(n);
    func(n);
}

он печатает:

in lvalue
in rvalue

Я не понимаю, что происходит во втором звонок. Как компилятор разрешить параметр шаблона ? Почему нет никакой двусмысленности ?

1 ответов


когда вы говорите func<double>(n), нет аргумента дедукции, так как вы указываете аргумент, и поэтому выбор между func(double &&) и func(const double &). Первый не жизнеспособен, потому что ссылка rvalue не может привязываться к lvalue (а именно n).

только func(n) выполняет вывод аргумента. Это сложная тема, но в двух словах, у вас есть два возможных кандидата:

T = double &:    func(T &&)       -->   func(double &)          (first overload)
T = double:      func(const T &)  -->   func(const double &)    (second overload)

первая перегрузка строго лучшая, потому что она требует одного меньше преобразование значения аргумента (а именно с double to const double).

волшебный ингредиент-это "справочники рушится", что означает T && может быть ссылка lvalue, когда T сам по себе является ссылочным типом (specificaly,double & && становится double &, и это позволяет существовать первому выводу).