简体   繁体   中英

C++11 auto and decltype

when reading about auto and decltype (C++11) i see the below function

auto findMin(A a, B b) -> decltype(a < b ? a : b)
{
    return (a < b) ? a : b;
}

this part -> decltype(a < b? a: b) is strange to me. what kind of function declaration or it just applies for auto and decltype only?

this part -> decltype(a < b? a: b) is strange to me. what kind of function declaration or it just applies for auto and decltype only?

The arrow -> following auto and the parenthesis, denotes a trailing return type, and it allows you to specify the return type after knowing the function parameters - more freedom if you will.

decltype gives us the declared type and this allows us to inspect the type of an expression.

In the ternary expression a < b? a: b a < b? a: b , the type of the expression is the common type between a and b . That is, for int and double the common type is double as int promotes to double .

Calling decltype with the mentioned expression decltype(a < b? a: b) then gives us the common type that will be the type of the return value that findMin returns. The function still needs to return a value and so we see the expression there as well.


Ps the common type behaviour of the ternary expression is captured by the std::common_type trait (since c++11)

decltype() is different from the auto keyword . We declare a variable in auto and we have to give it a first value. decltype() corresponds to a type. There are 2 separate sets of rules for decltype() .

1) decltype(name)

Examples;

decltype(x)
decltype(x.y)
decltype(ptr->a)

/*The compiler will look at what the type for this name is and think that- 
the type obtained with decltype is that type.*/

int ival;               decltype(ival) x; -----> int x;         
double dval;            decltype(dval) x; -----> double x;


 struct Data{           
    int mx;
    };

Data data;              decltype(data.mx) x; -----> int x;

Data *p=&data;          decltype(p->mx) x;   -----> int x;

Note : We can use decltype wherever we use type because decltype means type.

Note : const is ignored in auto keyword , but const is not ignored in decltype .

const int cx=10;        decltype(cx) y=10; -----> const int y=10;

Note : reference(&) is ignored in auto keyword , but reference(&) is not ignored in decltype .

int x=10;
int &r=x;
decltype(r) foo(); ----->  int& foo();

int x=10;
const int &r=x;
decltype(r) y=x;  -----> const int& y;

Note :No array to pointer conversion ( array decay ) in decltype .

int a[] {1,2,3,4};
decltype(a) b; -----> int b[4];

2) decltype(expression)

decltype (x)   -----> 1. Rule set
decltype ((x)) -----> 2. Rule set

All of the examples below will apply the 2nd rule set, so it's no longer a name but an expression .

decltype (10);
decltype (x+5);
decltype (x++);
decltype ((y));
decltype (*ptr);
decltype (a[5]);

Note : In this rule set, type inference depends on whether the expression is Lvalue , Rvalue , or Xvalue . Note : If the expression is a PRValue expression , the resulting type is directly the type of that expression.

decltype(10) x; // x is int.            
int x=20;       
decltype(x+4.5) dval;  // dval is double.

Note : If the operand of the decltype operator is not a name,if expression is in value category PRvalue expression , the type obtained with decltype is type T .If the expression is in the Lvalue expression value category, the type obtained with decltype is T& .If the expression is in the Xvalue expression value category, the type obtained with decltype is T&& .

If the expression is an Lvalue expression, examples of its status are given below.

int x=20;
decltype(++x) y=x;  -----> int & y;

int x=20;
int *ptr=&x;
decltype(*ptr) y=x; -----> int & y;

int a[10] [20] {};
decltype (a[2][5])  ----->int &;

int x=10;                                                       
decltype(x)   -----> int
decltype((x)) -----> Since the variable x is an Lvalue, the type of the expression is int&.

Note: The compiler does not generate an opcode for the expression that is the operand of the decltype operator

    int x=20;
    decltype(x++) y=45; -----> y is int.
    decltype(++x) y=x; -----> Since ++x is an Lvalue y is int&. x=20 because the compiler does not generate an opcode for the expression that is the operand of the decltype operator

C++11 allows two ways to declare a function's return type

  1. return_type function_name(arg1_type arg1, arg2_type arg2);

    Ex. int bar(int x, int y);

  2. auto function_name(arg1_type arg1, arg2_type arg2) -> return_type;

    Ex. auto foo(int x, int y) -> int

The first way is called ' prefix return type '. The second one, obviously is called ' suffix return type '. The 'suffix return type' is not just another fancy way to specify return types. It plays very important when doing generic programming.

Let me explain how.

'auto' type specifier is a great feature provided by C++11 which lets you define variables whose type can be deduced by the compiler. But there is a catch. The programmer needs to help the compiler deduce the type of an 'auto' variable using an initializer. For example, in case of

auto x = 100;

the compiler deduces type of x to be 'int' or in case of

auto y{'t'};

the compiler deduces type of y to be 'list of char'

Compiler's job of deducing the type is simpler when the initializer's type is simple and already known like above. But it is not always that simple. Sometimes, the data type of auto variable or return value is dependent on the type / computation of other variables. For example, in case of a template function, the return type needs to be determined based on the data type of input variables and/or the computation.

That is when decltype() specifier comes into the picture.

decltype(expr)

As it's name suggests, declaration type specifier, deduces type of an expression fed to it.

A rule of thumb I forgot to mention before, a compiler parses an expression left to right.

template<typename X, typename Y>
auto mul(X a, Y b) -> decltype(a*b)

Here, the compiler sees auto as a placeholder for the type that 'decltype' takes responsibility of deducing based on the expression it is fed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM