Post

C++ Tips : Type Deduction

Type deduction, Reference Collapsing.

C++ Tips : Type Deduction

My C++ Tips

Type Deduction


What is type deduction?

  • Compiler’s ability to automatically determine the type of a variable or expression.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
auto i = 10; // int
auto d = 3.14; // double
auto b = i > d; // bool

int ar[] = {1, 2};
auto p1 = ar; // int*


int x = 10;
const int cx = 5;
auto a = x; // int
auto b = cx; // still int , NOT const int

int* const p2 = &x;
auto c = p2; // int*

const int* p3 = &x;
auto d = p3; // const int*

int& r = x;
auto b = r; // int , NOT int&
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int x = 1;
int* p1 = &x;
const auto p2 = p1; // int* const

const int cx = 1;
auto& y = cx; // const int&

int a = 1;
int* const b = &a;
auto& c = b; // int* const&

auto& s = "Hello"; // const char(&)[6]

auto x[]; // error: auto requires initializer

The type of a variable can be a reference, but the type of an expression CAN’T

1
2
3
4
5
6
7
8
9
int x = 1;
int& r1 = x;
const int& r2 = x;

auto a = r1; // int
auto b = r2; // int

int&& r = 10;
auto c = r; // int

Type deduction : ternary operator

1
2
3
4
5
6
7
int x = 2, y = 4;
double z = 5.5;

auto i = x > 3 ? y : z;
// auto : double
// ternary operator is run-time process but
// type deduction is compile-time process

Type deduction : array

1
2
3
int arr[5] = {1, 2, 3, 4, 5};
auto p3 = arr; // int*
auto& p4 = arr; // int(&)[5]

Type deduction : func pointer

1
2
3
4
5
6
7
8
9
10
11
using F = int(int);
using FP = int(*)(int);

int foo() { return 0; }

auto fp1 = foo;   // int(*)(int)
auto fp2 = &foo;  // int(*)(int)
// They are same

auto f3 = foo;    // int(*)(int)
auto& f4 = foo;   // int(&)(int)

Reference Collapsing

  • & & becomes &

  • & && becomes &

  • && & becomes &

  • && && becomes &&

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef int&  lref;
typedef int&& rref;
int n;

// & & -> &
lref&  r1 = n; // type of r1 is int&

// & && -> &
lref&& r2 = n; // type of r2 is int&

// && & -> &
rref&  r3 = n; // type of r3 is int&

// && && -> &&
rref&& r4 = 1; // type of r4 is int&&

Why do we need it?

  • Reference collapsing enables perfect forwarding by preserving value categories.
  • T&& can be called with both lvalue and rvalue.
1
2
3
4
5
6
template<typename T>
void wrapper(T&& arg) 
{
    // T&& = forwarding reference
    process(std::forward<T>(arg)); 
}
This post is licensed under CC BY 4.0 by the author.