Language Runtime Enhancements

Language Runtime Enhancements

Reference: https://github.com/changkun/modern-cpp-tutorial

Lambda expression

Basic Syntax:
[capture list] (parameter list) mutable(optional) exception attribute -> return type {
// Function body
}

1
2
3
4
// Example
update(m, [](std::string key) -> long long int {
return;
});
  • capture list: a type parameter -> can serve to transfer external data to lambda expression.
    • Value Capture: Similar to parameter passing by value - Generated when it is created not when called.
      • value = 1, lambda (value), value = 100, lambda call -> lambda value = 1
    • Reference Capture: parameter passing by refernce
      • lambda value = 100
    • Implicit capture: Writing capture list is tired, so compiler supports many implicit ways
      • [] - empty capture list
      • [name1, name2] - captures series of variables
      • [&] - reference capture: compiler will decide which one to refer itself.
      • [=] - value capture: compiler execute the list of derivation applications itself.
    • Expression Capture: Above value and reference caputre capture lvalue (variable name) as it captures the ones that are outer scope. This capture allows captured members to be initialized with arbitrary expressions; rvalues. Type is being judged like auto.
1
2
3
4
5
6
7
8
9
10
// expression capture
void lambda_expression_capture(){
auto important = std::make_unique<int>(1);
// std::move : accept rvalue reference parameters - take the rvalue and move it
auto add = [v1 = 1, v2 = std::move(important)](int x, int y) -> int{
// Now value of important is not specified
return x+y+v1+(*v2); //as v2 = unique ptr
};
std::cout << add(3,4) << std::endl;
}

Generic Lambda

  • We learned auto cannot be used in the parameter list as it would conflict with the functionality of the template.
  • Lambda expression is not templated -> the parameter table cannot be generalized, hence the parameter table type must be clarified -> From C++14 you can use auto.
1
2
3
4
5
6
7
8
9
// From C++14, you can use auto keyword to generate generic meanings.
// Below is C++11

void lambda_generic(){
auto generic = [](auto x, auto y){
return x+y;
};
//...
}

Function Object Wrapper

std::function - generic, polymorphic function wrapper whose instances can store, copy, and call any target entity that can be called; a container of functions. -> We can more easily handle functions and function pointers as objects.

std::bind - solves the requirement that we may not always be able to get all the parameters of a function at one time.

std::placeholder::_N - Indicate nth element is not given yet, so when the parameters are given later, it fills from the front.

rvalue Reference

It solves a large number of historical issues in C++; extra overheads for vector,string, and allows the function object container, std::function possible.

  • lvalue: is a persistent object that still exists after an expression (not necessarily assignment expression). 주소값을 받을 수 있는 모든 것.
  • rvalue: is the temporary object that no longer exists after the expression ends. 참조 할 수 없는 값.
    • move(a) 는 a를 rvalue로 바꾸어서 lvalue 로 이동하는것; unconditionally conver lvalue -> rvalue
    • pvalue (pure): purely rvalue/literal like 10, true. Temporary variables returned by non-references, temp variables generated by operation expressions, origin literals, lambda expressions.
    • xvalue (expiring): A value that is destroyed but can be moved. -> T&&
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void reference(std::string& str){
std::cout << "lvalue" << std::endl;
}

void reference(std::string&& str){
std::cout << "rvalue" << std::endl;
}

int main(){
std::string lv1 = "string"; // lv1 is lvalue, "string" is rvalues
// std::string&& r1 = lv1; // illegal as rvalue cannot ref to lvalue.
std::string&& rv1 = std::move(lv1); // Legal -> move(lv1) convers lv1 to rvalue.

const std::string& lv2 = lv1 + lv1;

std::string&& rv2 = lv1 + lv2; // legal as lv1 + lv2 is a temp rvalue object.
// That is why below is Possible
rv2 += "new string";

reference(rv2); // output: lvalue -> because rv2 refers to rvalue -> rv2 is lvalue

int &a = std::move(1); // illegal - non-const lvalue ref cannot ref rvalue
const int &b = std::move(1); // legal

// lvalue must be const reference to reference rvalue
}

Move Semantics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

class A{
public:
int *pointer;
A() : pointer(new int(1)) {
cout << "ctor" << pointer << endl;
}

A(A& a) : pointer(new int(*a.pointer)){
cout << "copy" << pointer << endl;
} // meaningless object copy

// Move implementation
A(A&& a) : pointer(a.pointer){
a.pointer = nullptr;
cout << "move" << pointer << endl;
}

~A(){
cout << "dtor" << pointer << endl;
delete pointer;
}
};

A return_rvalue(bool test){
A a, b; // two ctor called
if (test) return a; // equal to static_cast<A&&>(a);
else return b; // equal to static_cast<A&&>(b);
}

int main(){
// rhs is xvalue: moving A(A(A&&)) to obj which is a pointer as rvalue
// and the pointer = nullptr -> object b becomes obj
// Therefore there is no dtor called
A obj = return_rvalue(false); // return b
}
// outputs:
// ctor 0xe7be70 (a)
// ctor 0xe7c2a0 (b)
// move 0xe7c2a0 (obj)
// dtor 0 (b)
// dtor 0xe7be70 (a)
// dtor 0xe7c2a0 (obj)

Above do not use copy constructs -> enhance performance

Perfect Forwarding
No matter what type of reference type the template parameter is, the template parameter can bederived as right reference type if and only if the argument type is a right reference.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void reference(std::string& str){
std::cout << "lvalue" << std::endl;
}

void reference(std::string&& str){
std::cout << "rvalue" << std::endl;
}

template <typenameT>
void pass(T&& v){
reference(v);
reference(std::move(v));
reference(std::forward<T>(v));
}

int main(){
pass("a"); // rvalue references
string b = "a";
pass(b); // lvalue references

// if both int -> lvalue???
// Depending on compilers?
}

reference contraction rule

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×