Which is better:
decltype((foo)) x = bar;
const decltype(foo)& x = bar;
If these are just two ways of saying the same thing, why are the parentheses even part of the language?
CodePudding user response:
If you want to declare "a reference to the same type of object as foo
", then I would prefer the second option. That's not really what the other form of decltype
is for.
The decltype
keyword pulls double-duty:
- It tells you the type of a variable
- It tells you the type and value category of an expression
That's what the extra parenthesis do. foo
is an identifier, so decltype(foo)
will tell you the type of the object identified by that identifier. (foo)
is not an identifier; it is an expression, so decltype((foo))
will tell you both the type and value category of it. It returns an lvalue-reference for an lvalue expression, an rvalue-reference for an xvalue, and a non-reference type for a prvalue.
For example:
int i = 10;
using A = decltype(i); // A is an alias for int
// because i is an identifer
using B = decltype((i)); // B is an alias for int&
// because (i) is an lvalue expression
using C = decltype(std::move(i)); // C is an alias for int&&
// because std::move(i) is an xvalue
// expression
using D = decltype(i 1); // D is an alias for int
// because i 1 is a prvalue expression
The value categories of all of the expressions in that example are obvious from looking at them, but consider a template:
template <typename Func>
void foo(Func func)
{
func(42);
}
The expression func(42)
could result in any value category, depending on the exact return type. That's where the expression form of decltype
becomes useful.