Я до сих пор не могу понять, зачем нам нужен шаблон для идеального fwd

У меня есть этот код: (живой, например: https://godbolt.org/z/js1qK9hd1)

struct big_class
{
    std::string s1;
    std::string s2;
    std::string s3;
    std::string s4;
    std::string s5;
    std::string s6;
    std::string s7;
};

void func(const big_class &bc)
{
    std::cout << bc.s1 << bc.s2 << bc.s3 << bc.s4 << bc.s5 << bc.s6 << bc.s7 << std::endl;
}

void fwd_func(big_class &&bc)
{
    func(std::forward<big_class>(bc));
}

template<typename T>
void prefect_fwd_func(T &&bc)
{
    func(std::forward<T>(bc));
}

int main()
{
    big_class bc{"1", "2", "3", "4", "5", "6", "7"};

    std::cout << "func" << std::endl;
    func(bc);
    std::cout << "fwd_func" << std::endl;
    fwd_func(bc);
    std::cout << "perfect_fwd_func" << std::endl;
    prefect_fwd_func(bc);
}

Итак, здесь fwd_func не работает - но, на мой взгляд, он в основном такой же, как шаблон perfect_fwd_func - только это не шаблон.

Почему это не работает? - он говорит, что не может привязать lval к ​​rval. Я думаю, это как-то связано с тем, что шаблон T && распадается на T или что-то в этом роде, но все равно не могу разгадать его вместе ... В чем разница между ними?

Если бы я хотел просто передать тип big_class - тогда я полагаю, что лучше всего просто передать его по константной ссылке ...


person code_fodder    schedule 16.06.2021    source источник
comment
связанный / обман: stackoverflow.com/questions/3582001/   -  person NathanOliver    schedule 16.06.2021
comment
@NathanOliver, это определенно связано, но я не думаю, что это совсем уж глупо (хотя я обязательно буду это читать), я конкретно спрашиваю разницу между T&& и _2 _... но я уверен, что там есть дубли, я просто еще не нашел их: p   -  person code_fodder    schedule 16.06.2021


Ответы (1)


В отличие от big_class&&, который является ссылкой rvalue и может принимать только ссылку rvalue, версия шаблона T&& является универсальной ссылкой / ссылкой для пересылки.

Когда вы передаете что-то в функцию-шаблон, T&& может быть выведен либо на ссылку rvalue (big_class&&), либо на ссылку lvalue (big_class&).

Таким образом, он может сгенерировать 2 разные функции для одного типа U:

void prefect_fwd_func<U>(U&& bc);

а также

void prefect_fwd_func<U&>(U& bc);

Вернитесь к своему коду:

fwd_func(bc);

Здесь bc не может быть передан как ссылка rvalue, он может быть передан только как значение или как ссылка lvalue.

Чтобы исправить это, вы можете создать отдельную функцию, которая принимает big_class& в качестве параметра:

void fwd_func(big_class& bc){...}

Или вы можете специально переместить bc в вызове функции:

fwd_func(std::move(bc));

Или создайте временную копию из bc:

fwd_func(big_class(bc));
person Ranoiaetep    schedule 16.06.2021
comment
универсальная ссылка - ›ссылка на переадресацию - person NathanOliver; 16.06.2021
comment
ах, это универсальная ссылка, различие между T&& и some_type&& - и его специфический вывод типа, который делает его универсальной ссылкой ... Думаю, я начинаю понимать это спасибо :) - person code_fodder; 16.06.2021
comment
@NathanOliver Добавлен универсальный справочник / справочник по пересылке. Я фанат Скотта Мейерса: D - person Ranoiaetep; 16.06.2021
comment
@RemyLebeau - ага, теперь мой вопрос, вероятно, дублирует ваш связанный вопрос - person code_fodder; 16.06.2021