тип автоматического возврата не выводит ссылку - PullRequest
7 голосов
/ 03 июня 2019

У меня есть следующий код:

#include <iostream>

struct C {
    int a;
    int& get() { return a; }
};
struct D {
    int a;
    int get() { return a; }
};
template <typename T>
auto foo(T o) { // no sample code is complete without a foo
    return o.get();
}

int main()
{
    C c;
    D d;
    c.a = 2;
    d.a = 42; // no sample code is complete without a 42
    std::cout << "c=" << c.a << ", d=" << d.a << "\n";
    c.get() = 3;
    //d.get() = 43;
    std::cout << "c=" << c.a << ", d=" << d.a << "\n";
    foo(c) = 4;  // <--- why won't this work?
    //foo(d) = 44;
    std::cout << "c=" << c.a << ", d=" << d.a << "\n";
}

Почему строка с пометкой не скомпилируется? Похоже, что копилер определяет тип возвращаемого значения foo<C> как int вместо int&, как я ожидал. Почему это так и как я могу получить его, чтобы вывести ссылку тоже?

http://coliru.stacked -crooked.com / а / 6ab909680836fd24

1 Ответ

6 голосов
/ 03 июня 2019

Учитывая auto, который объявлен как не-ссылка, поэтому мы имеем дело с передачей по значению.И auto следует правилам вычет аргументов шаблона ;ссылочная часть int& будет игнорироваться, тогда выводимый тип будет int.

. Вместо этого вы можете использовать decltype(auto) (начиная с C ++ 14).

типом является decltype(e), где e является инициализатором.

template <typename T>
decltype(auto) foo(T&& o) { // no sample code is complete without a foo
    return o.get();
}

Тип возвращаемого значения выводится как decltype(o.get()) и в соответствии с правилом decltype,

, если категория значения выражения lvalue, тогда decltype дает T&;

c.get(), возвращает int&,который является lvalue, тогда мы получаем тип возврата int& вместо int.

Кстати: обратите внимание, что если o все еще передается по значению, возвращаемая ссылка будет зависать.

...