Basic knowledge of decltype detail can be found "How decltype Deduces the
Type of an Expression: Case 1"
Case1: expression whose type is to be determined is a plain
variable or function parameter, like x, or a class member access,
like p->m_x. In that case, decltype lives up to its name: it
determines the type of the expression to be the declared type,
Case 2: If expr is an lvalue, then decltype(expr) is T&. If expr is an
xvalue, then decltype(expr) is T&&. Otherwise, expr is a prvalue, and
decltype(expr) is T.
The use of decltype(auto) is not limited to function return types. It
can also be convenient for declaring variables when you want to
apply the decltype type deduction rules to the initializing expression.
If you’re declaring variables inside a class. Instead of typing out the full
name of the type of the iterator, you can use decltype:, you can’t use auto.
This works because decltype doesn’t actually execute the expression given as
its argument– it is only used by the type checker to determine a type.
We could have also done the above example with declval. allows you to use
decltype without constructing the object,the type doesn’t even need a
default constructor, and in fact, it can be used with an incomplete type. The
above example could be rewritten as:
declval is commonly used in templates where acceptable template
parameters may have no constructor in common, but have the same member
function whose return type is needed.
result_of usage. result_of was introduced in Boost, and then included in
TR1, and finally in C++0x. Therefore result_of has an advantage that is
backward-compatible (with a suitable library). decltype is an entirely new
thing in C++, does not restrict only to return type of a function, and is a
language feature.