Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Significance of parentheses in decltype((c))?

I was reading this article on Wikipedia regarding C++11 Type Inference feature.

There is an example and I quote:

#include <vector>
int main() {  
    const std::vector<int> v(1);  
    auto a = v[0];        // a has type int  
    decltype(v[1]) b = 1; // b has type const int&, the return type of  
                          //   std::vector<int>::operator[](size_type) const  
    auto c = 0;           // c has type int  
    auto d = c;           // d has type int  
    decltype(c) e;        // e has type int, the type of the entity named by c  
    decltype((c)) f = c;  // f has type int&, because (c) is an lvalue  
    decltype(0) g;        // g has type int, because 0 is an rvalue  
}

in the following lines:

    decltype(c) e;        // e has type int, the type of the entity named by c  
    decltype((c)) f = c;  // f has type int&, because (c) is an lvalue  

What's the difference between c and (c)? Why does (c) represent an lvalue?

like image 705
MBZ Avatar asked Jan 02 '13 00:01

MBZ


People also ask

What does decltype mean in C++?

In the C++ programming language, decltype is a keyword used to query the type of an expression. Introduced in C++11, its primary intended use is in generic programming, where it is often difficult, or even impossible, to express types that depend on template parameters.

What does decltype stand for?

Decltype keyword in C++ Decltype stands for declared type of an entity or the type of an expression. It lets you extract the type from the variable so decltype is sort of an operator that evaluates the type of passed expression. SYNTAX : decltype( expression )

Does decltype evaluate expression?

The following expressions do not evaluate their operands: sizeof() , typeid() , noexcept() , decltype() , and declval() . Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior.

What is difference between decltype and auto?

auto is a keyword in C++11 and later that is used for automatic type deduction. The decltype type specifier yields the type of a specified expression. Unlike auto that deduces types based on values being assigned to the variable, decltype deduces the type from an expression passed to it.


2 Answers

  • c is the name of a variable;

  • (c) is an expression, in this case an lvalue expression, whose value is identical to the value of the variable c.

And the two are treated differently by decltype. Consider, for example, decltype(1+2), which is also an example taking an expression. It just so happens that your example is a simple version of an expression: one which merely names a single variable and does nothing exciting with it.

It's one of those differences that you generally only really care about if you're rationalising about the subtle parts of the language specification; though, as you have identified, it has quite a significant practical effect in this case.

Please note though that there is no operator usage here. It's all simply a deduction from the layout of the grammar.

like image 122
Lightness Races in Orbit Avatar answered Oct 08 '22 02:10

Lightness Races in Orbit


I found a good description here. It describes the difference between:

struct A { double x; };
const A* a = new A();
...
decltype(a->x) x4; // type is double
decltype((a->x)) x5; // type is const double&

and I quote:

The reason for the difference between the latter two invocations of decltype is that the parenthesized expression (a->x) is neither an id-expression nor a member access expression, and therefore does not denote a named object. [13]

Because the expression is an lvalue, its deduced type is "reference to the type of the expression", or const double&. [10]

like image 42
MBZ Avatar answered Oct 08 '22 01:10

MBZ