Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

auto return type not deducing reference

I have the following code:

#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";
}

Why won't the line marked compile? It seems that the copiler is deducing the return type of foo<C> to be int instead of the int& I would expect. Why is this and how can I get it to deduce the reference, too?

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

like image 755
Baruch Avatar asked Jun 03 '19 15:06

Baruch


People also ask

Can auto be a return type?

In C++14, you can just use auto as a return type.

Can auto be a reference?

The auto keyword by itself represents a value type, similar to int or char . It can be modified with the const keyword and the & symbol to represent a const type or a reference type, respectively.

What happens if I use decltype (auto) instead of return type deduction?

If you use the automatic return type deduction instead (with or without decltype(auto)), you won't get expression SFINAE and calling foobaron an instance of either Xor Ywill trigger a compile-time error. Share Follow edited May 13 2016 at 8:38 answered Apr 8 2013 at 14:44 MorwennMorwenn

What is auto auto in a function return type?

auto in a function return type or a lambda parameter implies template type deduction, not auto type deduction. Item 3: Understand decltype. decltype is an odd creature. Given a name or an expression, decltype tells you the name’s or the expression’s type. Typically, what it tells you is exactly what you’d predict.

What is an example of a decltype with Auto add?

As a very light example: template<typename T, typename U> auto add(T t, U u) { //almost deduced as decltype(t + u): decltype(auto) would return t + u; } I don't believe that would ever really be a problem, though I guess having the return type explicitly depend on the parameters could be clearer in some cases. Scenario 3

What is auto return type in C++14?

C++14 permits auto to indicate that a function’s return type should be deduced (see Item 3 ), and C++14 lambdas may use auto in parameter declarations. However, these uses of auto employ template type deduction, not auto type deduction. So a function with an auto return type that returns a braced initializer won’t compile:


1 Answers

Given auto, which is declared as a non-reference, so we're dealing with pass-by-value case. And auto follows the rules of template argument deduction; the reference part of int& will be ignored, then the deduced type is int.

You can use decltype(auto) (since C++14) instead.

type is decltype(e), where e is the initializer.

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

The return type is deduced as decltype(o.get()), and according to the rule of decltype,

if the value category of expression is lvalue, then decltype yields T&;

c.get() returns int&, which is an lvalue, then we get the return type int& insteand of int.

BTW: Note that if o is still passed by-value, the returned reference would be dangled.

like image 103
songyuanyao Avatar answered Oct 17 '22 02:10

songyuanyao