80

I rarely see decltype(auto) but when I do it confuses me because it seems to do the same thing as auto when returning from a function.

auto g() { return expr; }
decltype(auto) g() { return expr; }

What is the difference between these two syntaxes?

3 Answers 3

91

auto follows the template argument deduction rules and is always an object type; decltype(auto) follows the decltype rules for deducing reference types based on value categories. So if we have

int x;
int && f();

then

expression    auto       decltype(auto)
----------------------------------------
10            int        int
x             int        int
(x)           int        int &
f()           int        int &&
Sign up to request clarification or add additional context in comments.

9 Comments

But what if I did auto&& x = 5 then it would be int&& but if I do decltype(auto) x = 5 it would still be int&&.
@templateboy: no, the latter would just be int. Only xvalues become rvalue references.
@templateboy: If you're just declaring a variable, auto is by far more useful (e.g. if you have auto && for a universal reference). decltype is useful when you mainly want to operate with types (not variables), e.g. in traits that check if some expression has a certain type.
@templateboy: Yes, it's always the type of the expression, possibly with references added. If the expression is a CV-qualified value, that's retained. For details, see 7.1.6.2/4 ([dcl.type.simple]).
@soandos: No, then it'd be int. Only xvalues, not prvalues, become rvalue references.
|
25

auto returns what value-type would be deduced of you assigned the return clause to an auto variable. decltype(auto) returns what type you would get if you wrapped the return clause in decltype.

auto returns by value, decltype maybe not.

Comments

2

Simply put, when used as function return:

  • auto potentially drops cv-qualifiers and references.
  • decltype(auto) preserves cv-qualifier and reference-ness.

For example:

decltype(auto) func(int& x) // Equivalent to `auto& func(int& x)
{
return x;
}

decltype(auto) func(int&& x) // Equivalent to `auto&& func(int&& x)
{
return std::move(x);
}

decltype(auto) func(const int& x) // Equivalent to `const auto& func(int& x)
{
return x;
}

auto& func(const int& x) // Equivalent to `const auto& func(const int&x)
{
return x;
}

template <typename T>
auto func(T &&x) // Equivalent to `T func(T&& x)
{
return x;
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.