Почему этот параметр шаблона класса рассматривается как ссылка для пересылки? - PullRequest
1 голос
/ 26 апреля 2020

Согласно https://en.cppreference.com/w/cpp/language/reference, ссылки на пересылку являются либо

  1. функциональным параметром шаблона функции, объявленным как ссылка на значение.
  2. auto &&.

Здесь, в https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers Скотт Мейерс объяснил, что, хотя vector :: push_back (T && x) принимает T &&, это не универсальная ссылка. Это просто простая ссылка на rvalue.

Однако мой приведенный ниже код компилируется и работает хорошо:

#include <iostream>

template<typename T>
class MyClass
{
public:
    void f(T&& x)
    {
        std::cout << __FUNCSIG__ << std::endl;
    }
};

int main()
{
    int i = 10;

    MyClass<int&> myClass1;
    myClass1.f(i); //void __thiscall MyClass<int &>::f(int &)

    MyClass<int&&> myClass2;
    myClass2.f(10); //void __thiscall MyClass<int &&>::f(int &&)
}

Похоже, T && здесь рассматривается как ссылка для пересылки, потому что f (T && x) принимает ссылки как lvalue, так и rvalue. Но f (T && x) является членом шаблона класса; это не автономный шаблон функции. Это противоречит определению ссылки на пересылку, которое я упомянул выше?

<< \ ADD ->

В случае ссылки на пересылку в шаблоне функции сам шаблон функции также должен создание экземпляра на основе специфицированного c типа T. Мы можем express это явно:

template<class T>
void f(T&& x)
{}

int main() {
    int i = 10;
    f<int&>(i); // argument is lvalue
    f<int&&>(10); // argument is rvalue
}

f <\ int &> и f <\ int &&> - два разных экземпляра вышеуказанного шаблона функции. Они также не указывают на один и тот же адрес функции за кулисами, как в случае создания шаблона класса. Конечно, нам нужен объект класса, чтобы использовать его функции.

<- End ADD>

Ответы [ 2 ]

3 голосов
/ 26 апреля 2020

, поскольку f(T&& x) принимает ссылки как lvalue, так и rvalue

Это не так. Вы не сравниваете ту же самую функцию-член здесь. MyClass<int&>::f - это функция-член одного класса, которая принимает только значения l. Между тем MyClass<int&&>::f является функцией-членом другого класса и может принимать только значения r.

Шаблон класса не является классом. Это повар ie, из которого сделаны уроки. И, несмотря на специализации, имеющие функции-члены с одинаковыми именами, они по-прежнему являются разными функциями внутри разных классов.

Ваш код не будет успешно построен, если вы попытаетесь передать MyClass<int&>::f значение r,

myClass1.f(10); // ERROR

Свертывание ссылок заставляет сгенерированные f принимать ссылки различных категорий значений, но после создания экземпляра класса этот член будет принимать только определенную c категорию значений. Это не переадресация категории значения, которая выводится на сайте вызова, как это делает ссылка на переадресацию.

0 голосов
/ 26 апреля 2020

Особенность пересылки ссылок в том, что они автоматически становятся ссылками rvalue или ссылками lvalue во время вывода аргументов шаблона. Вызывающей стороне не нужно указывать, что они хотят.

В вашем примере вы явно указали int& и int&&, что заставляет f иметь один или другой тип. И затем он принимает lvalue или rvalues ​​соответственно, но не оба, как ссылка для пересылки: myClass1.f(10); и myClass2.f(i); оба плохо сформированы.

...