about temporary objects...

It is said about C++ 17, that if expressions instead of names are passed to decltype(auto), then the deduced type depends on the value category of the expression:

1- type for a prvalue (e.g. temporary)
2- type& for an lvalue (e.g. objects with names)
3- type&& for an xvalue (e.g. objects marked with std::move)

Is this correct?

-----------------------------------
Does retTemp below return a temporary object?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
	struct C
	{
		int val;
	};

	decltype(auto) retTemp()
	{
		return C{ 4 };
	}
        
	decltype(auto) retLocal()
	{
                C c{4};
		return c;
	}



retTemp returns a temporary right? retLocal returns a local (stack ) object- does it return a copy or trash? Or are both functions equivalent?

How does decltype(auto) alter the return type in each of the functions above?

This is probably very basic stuff...

Regards,
Juan
Last edited on
In short, I believe both will be deduced to simply return type C.

More explanation below...

This is probably very basic stuff...
Not at all! You are asking the right questions. I imagine there's only a small percentage of the C++ community that really understands C++14/17 features in-depth (luckily, people like Cubbi, JLBorges and others visit this site :)). I don't really even understand the nuances of auto/decltype myself... so someone else might want to confirm what I say.

First, this doesn't answer your question from a language-lawyer perspective, but in your particular case, here's a trick you can do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct C
{
	int val;
};

decltype(auto) retLocal()
{
	C c{4};
	return c;
}

C& retLocalBad()
{
	C c{4};
	return c;
}

int main()
{
	C& c1 = retLocal(); // Compiler error!
	// error: cannot bind non-const lvalue reference of type ‘C&’ to an rvalue of type ‘C’
    
	C& c2 = retLocalBad(); // Compiler *warning*
	// warning: reference to local variable ‘c’ returned [-Wreturn-local-addr]
}


Because C& c1 = retLocal(); simply does not compile, it means that the return type of retLocal cannot be C&.

_________________________________________________

Another observation, which doesn't completely answer your question, but sheds a clue:

Take a look at the example @ https://en.cppreference.com/w/cpp/language/auto
1
2
3
    auto c0 = a;             // type of c0 is int, holding a copy of a
    decltype(auto) c1 = a;   // type of c1 is int, holding a copy of a
    decltype(auto) c2 = (a); // type of c2 is int&, an alias of a 

c1 is just an int, which is equivalent to your "return c;" line. It just becomes C.

_________________________________________________

Finally:

In retTemp, C{4} is a temporary and a prvalue, like you said.
According to https://en.cppreference.com/w/cpp/language/decltype
C{4} is not an unparenthesized id-expression or an unparenthesized class member access expression, so it must be (2c), which says if the value category of expression is prvalue, then decltype yields T.

In retLocal, c is an unparenthesized id-expression (to my understanding), so "decltype yields the type of the entity named by this expression", where the entity here is the C object.
Last edited on
if expressions instead of names

key point you know but missed in "retLocal"

How does decltype(auto) alter the return type in each of the functions above?

They both return C, by value.

retTemp returns a temporary right?

the function-call expression retTemp() is a prvalue expression. Technically it's not "a temporary" since C++17 changed the meaning of "prvalue", but conceptually you're in the ballpark.

retLocal returns a local (stack ) object- does it return a copy or trash?

It uses RVO. If RVO is disabled by -fno-elide-constuctors or equivalent, it moves from the local variable into the result object. If move is disabled due to missing move constructor, then it will copy.

Now if you change retLocal to return (c);, it will return lvalue reference to C, which becomes a dangling reference as soon as the function returns, or "trash" as you put it.
Thanks to the both of you!!

Regards,
Juan
Topic archived. No new replies allowed.