The University of Iowa
The College of Liberal Arts and Sciences
Department of Computer Science
Programming Languages and Tools:
CS:3210:0001
Lecture/Lab #29
Programming with C++
Lambda expressions (cont.), exceptions, namespaces
Warm up: algorithms
- What are some notable characteristics of standard library algorithms?
- How do we write an algorithm that appends its output to the end of another container?
std::vector<int> src = { 11, 22, 33, 44, 55, 66, 77 };
std::vector<int> dst;
std::transform( src.begin(), src.end(), ???, []( int n ) {
return n + 100;
});
- If algorithms operate on iterators only, how do algorithms like remove and remove_if work?
std::remove_if( src.begin(), src.end(), [](int n) {
return n % 2 == 0;
});
Exercise 1
Sort the vector, erase all "Bob" occurrences and print the vector to the standard output using only standard algorithms
-
Open the exercise template
-
Write your code, press Run to test
-
When you're done, grab your Repl's link and send it as a direct message to me (agurtovoy)
-
Click on the corresponding option in the "Lab29 exercises" poll in #general
Lambda expressions (cont.)
A convenient way to define an anonymous function object at the point of use
std::vector<int> v = { 11, 22, 33, 44, 55, 66, 77 };
auto iter = std::find_if( v.begin(), v.end(), []( int n ) {
return n > 42;
} );
-
The [] syntax actually serves a purpose and is called a capture clause.
-
The empty brackets indicate that the expression body of doesn't accesses any variables from the enclosing scope.
-
Use [=] to enable capturing all outside variables by value, [&] to capture by reference.
-
Beware of lifetime issues if/when passing/returning lambda from a function.
Error handling options in C++
- Throwing an exception
- Returning a value indicating failure
- Terminating the program
Throwing an exception
int main()
{
try {
std::cout << "Hi there" << std::endl;
throw std::runtime_error( "No pasarán" );
std::cout << "Hi again" << std::endl;
}
catch ( std::exception const& x )
{
std::cout << "\nUh-oh: " << x.what() << std::endl;
}
}
List of standard exception types:
When to throw an exception
- Rare errors / errors that should not be ignored (e.g. out of memory)
- An error that cannot be handled by an immediate caller (e.g. network outage)
- No suitable return path for errors codes are available (e.g. constructors).
- The code flow is made more complicated or expensive by a need to pass both a value and an error indicator back.
- When in doubt, prefer exceptions.
When to return an error code
- A failure is normal and expected (e.g. opening a file).
- An immediate caller can reasonably be expected to handle the failure.
Consider using std::optional and std::variant if choosing this route.
When to terminate
- Unrecoverable errors (e.g. memory exhaustion)
Namespaces
namespace cs3210 {
struct point {
int x;
int y;
};
point add( point const& l, point const& r )
{
return point{ l.x + r.x, l.y + r.y };
}
} // namespace cs3210 {
int main() {
cs3210::point p1{ 1, 15 };
cs3210::point p2{ 10, -5 };
auto p3 = add( p1, p2 );
}
A mechanism for preventing name conflicts in large projects
Programming with C++, Fall 2019, Lecture #29
By Aleksey Gurtovoy
Programming with C++, Fall 2019, Lecture #29
Lambda expressions (cont.), exceptions, namespaces
- 655